Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.71/35: Рейтинг темы: голосов - 35, средняя оценка - 4.71
7 / 7 / 5
Регистрация: 25.03.2018
Сообщений: 377

Параллельное обслуживание TCP сокета

19.08.2021, 17:42. Показов 7945. Ответов 29

Студворк — интернет-сервис помощи студентам
Появился следующий вопрос, как будет отрабатывать следующий кусок кода, если на сокет придет два запроса параллельно, либо первый запрос будет долго обрабатываться и тут накатиться еще и второй:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    public class StateObject
    {
        public int bufSize = 256;
        public int port = -1;
        public byte[] buffer = null;
        public string message = null;
        public Socket workSocket = null;
 
        public StateObject() { }
 
        public StateObject(int port)
        {
            this.port = port;
 
            workSocket = new Socket(ProxyServer.ipAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);
        }
    }
 
    public void StartListener()
        {
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, state.port);
 
            try
            {
                state.workSocket.Bind(localEndPoint);
                Log.Info("Started TCP Socket server");
 
                while (true)
                {
                    using (Socket listener = state.workSocket.Accept())
                    {
                        int size = 0;
                        state.buffer = new byte[state.bufSize];
                        StringBuilder sb = new StringBuilder();
 
                        // Get request
                        Log.Info("Read data...");
                        do
                        {
                            size = listener.Receive(state.buffer);
                            sb.Append(Encoding.UTF8.GetString(state.buffer, 0, size));
                        }
                        while (listener.Available > 0);
 
                        state.message = sb?.ToString();
 
                        // do something...
                    }
                }
 
            }
            catch (Exception Ex)
            {
                Console.WriteLine(Ex.ToString());
            }
        }
Я бы хотел, чтобы запросы могли обрабатываться параллельно, в этом коде так и будет или что-то переписать нужно?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.08.2021, 17:42
Ответы с готовыми решениями:

Сцена зависает при запуске TCP-клиента, когда он подключен к TCP - серверу, при этом TCP-клиент полностью функционирует
Проблема описана в заголовке, и хотелось бы услышать ваше мнение, о том как можно решить проблему. Скрипт TCP-клиента на сцене: ...

Соединить 2 слушающих TCP сокета так, чтобы данные ходили между ними прозрачно
День добрый, господа. Задача простая на первый взгляд - необходимо соединить 2 слушающих TCP сокета так, чтобы данные ходили между ними...

Определение состояния сокета в TCP сервере
Здравствуйте коллеги! Я пишу TCP сервер c использованием расширения Sockets. Порывшись в руководстве, я так и не понял, как...

29
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.08.2021, 23:04
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от cinekst_207 Посмотреть сообщение
я думал он не будет ее ставит, если не приводить к строке.
Дык GetString уже возвращает строку, которая потом в буфер добавляется.
Уже на этом этапе будет заглушка.
0
7 / 7 / 5
Регистрация: 25.03.2018
Сообщений: 377
27.08.2021, 00:24  [ТС]
Someone007, я довел до такого состояния, по идее, на каждого клиента будет создаваться бесконечная ожидалка на запросы от них, при чем это будет асинхронно, а значит цикл while продолжит свою работу дальше:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    class Server
    {
        private TcpListener listener = null;
        private IPAddress iPAddress = IPAddress.Any;
        private int port = 8080;
 
        public Server()
        {
            listener = new TcpListener(iPAddress, port);
            listener.Start();
        }
 
        public async void StartAccepting()
        {
            while (true)
            {
                Console.WriteLine("Waiting new socket...");
                Socket client = listener.AcceptSocket();
                Console.WriteLine($"Accepted socket: {client.RemoteEndPoint}");
 
                await DoAction(client);
            }
        }
 
        private Task DoAction(Socket client)
        {
            int size = 0;
            byte[] buffer = new byte[10];
            StringBuilder sb = new StringBuilder();
            Queue<string> strings = new Queue<string>();
 
            // Get request
            Console.WriteLine("Read data...");
            while (client.Connected && (size = client.Receive(buffer)) > 0)
            {
                // do something...
            }
            return Task.CompletedTask;
        }
    }
Добавлено через 48 минут
А нет, у меня ожидалка второго клиента запускается только если первый клиент закончился, не то, мне нужно, чтобы после первого клиента, искался второй.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.08.2021, 01:13
C#
1
_ = Task.Run(() => DoAction(client));
1
7 / 7 / 5
Регистрация: 25.03.2018
Сообщений: 377
27.08.2021, 01:22  [ТС]
kolorotur, что это за магия? КАК?
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
27.08.2021, 10:39
Цитата Сообщение от cinekst_207 Посмотреть сообщение
client.Connected
Вот это свойство живет какой-то своей жизнью. Я один раз пытался на него завязаться, но оно все равно высвечивало true на уже закрытом потоке.

Цитата Сообщение от cinekst_207 Посмотреть сообщение
меня каждый запрос от клиента будет заканчиваться на \n
есть сериализация json,xml,binary. Ну или хотя бы TcpClient, который умеет в Stream, а соответственно можете работать с TextReader.ReadLine
1
7 / 7 / 5
Регистрация: 25.03.2018
Сообщений: 377
27.08.2021, 11:01  [ТС]
Wolfdp, да я думал об этом, но решил обойтись без создания всяких подобных ридеров. Хотя стоит попробовать.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
27.08.2021, 11:55
Цитата Сообщение от cinekst_207 Посмотреть сообщение
но решил обойтись без создания всяких подобных ридеров.
На самом деле это наиболее оптимальный вариант...
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
27.08.2021, 12:50
cinekst_207, не ведитесь -- та еще наркота. Один раз попробуете, и потом постоянно будете вместо того чтобы считывать в буфер, валидировать сколько считало, делать оооотступы-дочиииитку-сдвииииги тупо вызывать СделатьОперацию(Поток) и даже не задумываться что где-то может возникнуть проблема. Лапки начинают грустить, т.к. ими приходится меньше делать "клац-клац"...

А если серьезно: Tcp протокол вообще по своей идеологии один-в-один с Stream, а для последнего в C# предусмотрено 100500 готовых решений, как в базовой комплектации, так и во всех либах.
0
7 / 7 / 5
Регистрация: 25.03.2018
Сообщений: 377
28.08.2021, 15:35  [ТС]
Wolfdp, ну, я сделал через потоки, только вот проблема в том, что есть заглушка в виде new byte[1], чтобы знать, пришли новые данные или нет.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Server
    {
        private TcpListener listener = null;
        private IPAddress iPAddress = IPAddress.Any;
        private int port = 8080;
 
        public Server()
        {
            listener = new TcpListener(iPAddress, port);
            listener.Start();
        }
 
        public void StartAccepting()
        {
            while (true)
            {
                Console.WriteLine("Waiting new socket...");
                TcpClient client = listener.AcceptTcpClient();
                Console.WriteLine($"Accepted socket: {client.Client.RemoteEndPoint}");
                _ = Task.Run(() => DoAction(client));
            }
        }
 
        private Task DoAction(TcpClient client)
        {
            NetworkStream stream = null;
            try
            {
                // Get request
                Console.WriteLine("Read data...");
                while (client.Client.Receive(new byte[1]) > 0)
                {
                    stream = client.GetStream();
                    if (stream.CanRead)
                    {
                        byte[] buffer = new byte[client.ReceiveBufferSize];
                        stream.Read(buffer, 0, client.ReceiveBufferSize);
                        string s = Encoding.UTF8.GetString(buffer);
                        stream.Write(Encoding.UTF8.GetBytes($"Server get this {s} data"));
                        stream.Flush();
                    }
                }
            }
            catch
            {
                Console.WriteLine($"Close socket: {client.Client.RemoteEndPoint}");
                client.Client.Shutdown(SocketShutdown.Both);
                stream.Close();
                client.Close();
            }
            return Task.CompletedTask;
        }
    }
Добавлено через 6 минут
А еще есть такой странный баг, если в stream.Write($"123 {str} 4"); передаваемую строку поставить в середине, то почему-то все, что находится дальше, в данном случае цифра 4, не будет в передаваемом сообщении.

Добавлено через 19 минут
Все-таки плохая идея с потоками, поток при каждом новом запросе нужно реинициализировать.
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
28.08.2021, 16:32
Цитата Сообщение от cinekst_207 Посмотреть сообщение
Все-таки плохая идея с потоками, поток при каждом новом запросе нужно реинициализировать.
Нет, просто вы не знаете как со всем этим работать (в целом для начинающего ожидаемо, я в первый раз городил проект через BeginRecive). Самый простой способ отправки текстовых данных.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//код написан на c# ver 9, в проектах со старыми версиями потребуюется убрать часть сахара
 
        private async Task DoAction(TcpClient client)
        {
            try
            {
                Console.WriteLine("Read data...");
                using var stream = client.GetStream();
                var encoding = Encoding.UTF8;
                using var reader = new StreamReader(stream, encoding);
                using var writer = new StreamWriter(stream, encoding);
                var data = default(string);
                while (!string.IsNullOrEmpty(data = await reader.ReadLineAsync()))
                {
                    //Example:
                    Console.WriteLine(data);
                    await writer.WriteLineAsync($"reviced message text size { data.Length }");
                    await writer.FlushAsync();
                }
                Console.WriteLine($"Close socket: {client.Client.RemoteEndPoint}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Close socket with error: {client.Client.RemoteEndPoint}\n{ex}");
            }
        }
Зачем вам передавать 1 байт и что там решили реинициализировать я даже разбирать не хочу.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.08.2021, 16:32

XmlSerializer Xml- сообщений из Tcp сокета
Добрый день ! Хочу написать клиентское приложение . Суть такова принимать xml сообщения и понимать что принял . Формат пакетов :...

C#. Пишу свою ICQ (TCP). Трабл с чем-то по части сокета
Здравствуйте! Я хорошо знаю C#, но возможно что мне не хватило знаний написать хороший &quot;движок&quot; для работы по TCP протоколу. ...

Как передать принятые данные из TCP сокета в функцию обработки
Имеется программа TCP клиент, которая принимает данные от TCP сервера и в дальнейшем их обрабатывает. Возникла проблема с тем, чтобы...

Написать соединение: много клиентов - сервер (Winsock; на сервере 3 сокета: 2 TCP и 1 UDP)
Всем здрасьте !!!! Мне надо написать соединение: много клиентов - сервер Тут мне надо иметь на сервере 3 сокета: 2 TCP и 1 UDP ...

Использование не блокируемого WinSock TCP сокета. Реализации таймаута для ожидания connect()
Необходимо реализовать TCP подключение и обменяться данными. В случае не доступности узла, к которому осуществляется подключение, функция...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
GitHub Copilot в JetBrains: модель по умолчанию, Fix и контроль MCP
and_y87 12.10.2026
10 октября 2026 года GitHub обновил Copilot для JetBrains: добавил настройки стартовой модели, исправления из диагностики и управление автозапуском MCP. Поддержка IDE 2025. 1 прекращена — требуется. . .
День 5 из 28: Codex подсказывает следующий запрос
and_y87 12.10.2026
9 октября 2026 года OpenAI запустила бету Composer predictions — подсказок следующего сообщения в текущем диалоге Codex. Это помощь с формулировкой запроса, а не автоматическое продолжение задачи. . . .
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru