Сервер + Клиент

Привет всем!
Пишу простой клиент+сервер.
Сервер генерит рандомное число каждую секунду и отправляет это число клиенту, клиент просто выводит числа на экран(в реальном времени)
Столкнулся с таким:
Невозможно вычислить выражение, поскольку фрейм машинного кода находится на вершине стека вызовов.
И это пишется везде, в смысле приложение вроде бы как работает, но на самом деле висит. А вот ошибка эта в отладчике, на пример в переменной sListener типа Socket

Сервер:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Random rnd = new Random();
        public Form1()
        {
            Server();
            InitializeComponent();
        }
        public void Server()
        {
            IPHostEntry ipHost = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = ipHost.AddressList[1];
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

            Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                sListener.Bind(ipEndPoint);
                sListener.Listen(10);

                while (true)
                {
                    //label4.Text = "Ожидаем соединение через порт: " + ipEndPoint;

                    Socket handler = sListener.Accept();
                    string data = null;

                    string reply = label3.Text;

                    byte[] msg = Encoding.UTF8.GetBytes(reply);
                    handler.Send(msg);

                    if (data.IndexOf("<TheEnd>") > -1)
                    {
                        label4.Text = "Сервер завершил соединение с клиентом.";
                        break;
                    }

                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                Console.ReadLine();
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            int temp = rnd.Next(7000, 12000);
            label3.Text = Convert.ToString(temp);
        }
    }
}

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Решил метод Server попробовать выполнить в другом потоке, но не выходит.(
Thread my = new Thread(Server); my.Start(); Но никак не могу понять почему он(метод) не выполняется. Если написать какой-нибудь простенький метод и вставить его вместо Server Thread my = new Thread(Example); то Example успешно будет выполняться параллельно, а Server не хочет. В чем может быть проблема?

Откуда вывод что он не выполняется? Брейкпоинт ставишь, в дебагере смотришь?
Метод accept, и send в таком виде будут блокировать выполнение потока до того момента пока не будет осуществлено подключение, или не будет завершена отправка данных.
Но из того что ты написал

Thread my = new Thread(Server); my.Start();
сделать вывод о том, почему оно у тебя не работает — нельзя.
Если ты не поняло и не исправил все остальные ошибки, то лишь от переноса кода в отдельный поток — оно у тебя не заработает. И уж тем более если ты продолжаешь использовать лейблы (их текст) как переменные. Обращение к контролам не из основного потока, требует дополнительного кода.
Я бы рекомендовал для начала сделать консольное приложение без отдельного потока.

java сразу — это пипец, в этом твоя основная проблема. научись/попробуй сначала написать это на с, потом на c++, и только потом, если это жутко оправдано — переноси часть кода на java. псевдоумных архитекторов, которые свистят об обратном или посылай сразу или меняй работу ;)

Это С#. Действительно, лучше слушать умных людей, которые даже не могут понять, на каком языке код написан, и прочитать тег.

А что есть разница на чем неуметь писать ? Если c#, то лучше сразу застрелиться — избавить и себя и мир от этих мучений ;)

P.S. теги не читаю принципиально — всегда думал, что они предназначены не для чтения, а для поиска

1. Я вижу цикл для аццепта внутри конструктора формы. Ты вешаешь инициализацию формы на неопределенный период времени, может это ни к чему и не приведет, но может лучше запускать листенера по кнопочке на форме? А ещё лучше в отдельном потоке, что бы не блокировать UI. Или же использовать асинхронный вариант сокет методов.
2. Нет, все таки то что ты вызываешь инициализацию, приводит к тому, что InitializeComponent ещё не вызван на тот момент когда ты начинаешь работу с подключенным клиентом, label4 и label3 — не инициализированы, ты не можешь обращаться к их полям в методе Server.
3. string data не инициализирован ничем кроме null, но ты вызываешь indexOf
4. Опять же, не уверен что таймер вообще выполняется до того как клиент отключился (форма не инициализирована, делегат timer1_Tick не подключен и таймер не инициализирован). В таком виде.

Извини, но я вижу по этому куску кода что ты ленишься свой же код внимательно читать, или же не знаешь что перед тем как работать с обьектом его нужно сконструировать, инициализировать переменную. Что не ориентируешься в потоке выполнения — что после чего и где выполняется, или же не разбираешься в WindowsForms. Рекомендую что-то для начала почитать, про C#.
Ещё, методы принято называть глаголами, то-есть не Server, а StartListen или StartServer.

Невозможно вычислить выражение, поскольку фрейм машинного кода находится на вершине стека вызовов.
Как оно работает я понять не могу, оно должно падать с другими ошибками, с более внятным описанием. Опять же, как ниже написали — ipHost.AddressList[1] — может не содержать 2 адреса, а только один, и первый элемент тут имеет индекс 0.

EDIT:

все таки то что ты вызываешь инициализацию
должно быть, «то что ты вызываешь метод перед инициализацией».

Как все запущено. Перепишите это на C++. Уберите WindowsForms. Для клиент-сервера окошки вредны.
И не читайте MSDN. Во всем что касается сети и псевдосовместимости с POSIX он полон ошибок.

А вообще

ipHost.AddressList[1];
кажись 0 должен быть.

В этом коде много проблем, но это точно не WindowsForms, или MSDN.
Вообще это показатель высокого профессионального уровня, когда человек не вчитавшись в код спешить обвинить во всем «окошки» и MSDN. Не говоря уже о шаблонно дежурной фразе про «что касается сети и псевдосовместимости с POSIX он полон ошибок». Причем тут это в данном случае, с простым приложением которое просто принимает коннекты по TCP, и пишет строчку текста в ответ? Может в .NET сокеты поломанные и не работают?

Шарик, вы балбес. Этот код явная копипаста из MSDN msdn.microsoft.com/...60993d(v=vs.90 включая номер порта.

И как раз в первую очередь это касается «простых приложений которые принимают коннекты по TCP».

Не спорьте о вкусе устриц с теми кто их ел.

Этот код не работает не потому что он «копипаста с MSDN».

То что в этом коде используется фрагмент с MSDN, никак не является подтверждением ваших бредовых заявлений выше. Если хотите продолжать адекватную дискуссию, пожалуйста продемонстрируйте где ошибка в коде на MSDN, и что код представленный в теме, не работает именно по этой причине.

Хотя для меня и так очевидно, что вы этого сделать не можете. Этот код не работает потому что автор допустил множество ошибок, а не потому что это WindowsForms, или «не C++», и не потому что часть кода взята с MSDN.

EDIT:
Даже индекс для AddressList там 0, а не 1.

Навскидку. Стандарт cfajohnson.com/...rface-POSIX.pdf
Страница 1525.
MSDN msdn.microsoft.com/...1(v=vs.85).aspx

Читаем в стандарте “Otherwise, −1 shall be returned, and errno shall be set to indicate the
error.”. Читаем в MSDN: “... or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, WSAGetLastError can be used to retrieve a specific error code.”

Это о следовании стандарту.

А вот явных ошибок в примерах, там где я их видел, сейчас найти не могу. 5 лет назад точно еще была в примерах к winsock. Сейчас причесали.

Ок, есть несоответствие стандарту.
Нужно сначала разобраться, это ошибка в документации, или реализация отличается от стандарта?
Если это отличие в реализации winsock, тогда MSDN как раз верный источник информации, и можно разве что опечалится что реализовали не совсем по стандарту.
Если же ошибка в документации, тогда поскольку ссылка на описание функции WinAPI для вызова из под C++, стоит сначала проверить, как выглядит описание для функций сокетов .NET. В добавок про ошибку можно было написать фидбек, на том же MSDN.

А вот явных ошибок в примерах, там где я их видел, сейчас найти не могу. 5 лет назад точно еще была в примерах к winsock. Сейчас причесали.
А есть не явные? Опишите какие там неявные ошибки. Опять же, если там нету ошибок, о чем тут говорить? Может вы знаете серьёзные ошибки (не несоответствие стандарту, а именно ошибки которые приводят к некорректному поведению приложения, и невозможности написать приложение для работы с сетью?) в том как сокеты реализованы в .NET?

Но опять же, я не вижу никакого повода считать что человек что-то делает ориентируясь на POSIX стандарт. Люди (в том числе и я таким занимался) пишут программы работающие с сокетами на .NET в том числе используя WindowsForms, и они работают. Повторяюсь. Представленный в теме код не работает, потому что в нем ошибки допущенные автором, а не потому что это С#, .net, WindowsForms, или то что использовать фрагмент примера с MSDN. Поэтому считаю ваше замечание по поводу переписывания на С++ - не корректным и несправедливым по отношению к языку, платформе, библиотеке WindowsForms и MSDN.

EDIT:
Стойте, а какое значение у константы SOCKET_ERROR, случайно не −1?
Если да, то в чем проблем? В обоих случаях возвращается −1, и нужно идти смотреть отдельно, что там за ошибка.

EDIT2:
К .NET как бы оно не совсем относится вообще, так как там (к счастью, и благодаря достижениям в области высокоуровневых языков) в случае ошибки кидается Exception нужного типа, что в MSDN и написано.

EDIT:
Стойте, а какое значение у константы SOCKET_ERROR, случайно не −1?
Если да, то в чем проблем? В обоих случаях возвращается −1, и нужно идти смотреть отдельно, что там за ошибка.

Вы забыли про errno.

Под словом «явные» я имею в виду ошибки видимые без попытки компиляции. Раньше, если я не ошибаюсь, то ли для select то ли для send на MSDN был пример который не компилировался VS.

Да я не спорю, писать можно на любом языке. Мало того, я скажу что когда я писал на C# он мне даже понравился.

PS Не смотря на все это, когда я вижу в «серверном» коде


public partial class Form1 : Form
{
....
public Form1()
{
Server();

меня начинает передергивать.

Підписатись на коментарі