Зависание серверной программы на C#

339
06 августа 2017, 05:48

Написал две простые программы: клиент, сервер. По нажатию кнопки, в окне программы клиента, клиент отправляет серверу сообщение (кодированное в байтах), введённое пользователем, и получает ответ от сервера - длину раннее отправленного сообщения. Но сервер не работает - зависает при нажатии кнопки начала работы. Хотя сервер устанавливает соединение и пользователь получает ответ от сервера. Вот основная часть кода сервера:

private void button1_Click(object sender, EventArgs e)
    {
        textBox1.Text = "Сервер запущен";
        IPHostEntry ipHost = Dns.GetHostEntry("localhost");
        IPAddress ipAddr = ipHost.AddressList[0];
        IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 8888);
        Socket sock = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            sock.Bind(ipEndPoint);
            sock.Listen(10);
            while (true)
            {
                textBox1.Clear();
                textBox1.Text = "Получаем данные. Порт " + ipEndPoint;
                Socket s = sock.Accept();
                string data = null;
                byte[] bytes = new byte[1024];
                int bytesCount = s.Receive(bytes);
                data += Encoding.UTF8.GetString(bytes, 0, bytesCount);
                textBox2.Text = "\n Получено: " + data;
                string reply = "Query size: " + data.Length.ToString() + " сhars";
                byte[] msg = Encoding.UTF8.GetBytes(reply);
                s.Send(msg);
            }
        }
        catch (Exception ex)
        {
            textBox1.Text = ex.ToString();
        }
    }

Для справки скриншоты окна программ сервера и клиента:

Answer 1

У вас сервер не завис. Он вполне себе работает и отвечает на запросы, но делает это в UI потоке вашего приложения (этот поток отвечает за прорисовку и работу пользовательского интерфейса).

Вам нужно вынести цикл работы серверного кода в отдельный поток. Для этого можно воспользоваться возможностями TPL библиотеки которая входит в состав .net (https://msdn.microsoft.com/ru-ru/library/dd460717(v=vs.110).aspx)

Переходя к многопоточной архитектуре нужно учитывать множество моментов. Самый простой момент это взаимодействие кода в отдельном потоке с UI элементами форм (окон), т.е. из другого потока нельзя вот так просто изменить хоть какой нибудь UI элемент (вот тут есть множество примеров https://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c)

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

READ ALSO
Как заставить Particle.Systems следовать за касанием

Как заставить Particle.Systems следовать за касанием

Я пытался так но частицы не появляются на позиций касания

276
Работа с DOCX без WORD

Работа с DOCX без WORD

Посоветуйте библиотеку для работы с *DOCX без использования самого WORD(INTEROP)

256
При выборе Prefab-а crash Unity3d

При выборе Prefab-а crash Unity3d

Открываю Юнити нажимаю на Prefab и Юнити выключается, никакой ощибки не выдаёт просто закрывает юнити и всё, может кто знает почему

300
Joystick connect WPF, C#

Joystick connect WPF, C#

Есть приложение на WPF заказчик хочет управлять программой джойстиком типа "joystick cyborg x" (без клавиатуры и мышки)

419