С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/18: Рейтинг темы: голосов - 18, средняя оценка - 4.89
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54

TCP (Клиент-сервер) - потеря данных

18.04.2017, 09:21. Показов 3832. Ответов 22

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

Клиент
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
 
namespace сlient
{
 
    class Program
    {
        const int startCount = 10000;
        static int countClient = 0;
        static int countServer = 0;
        Guid guid = Guid.NewGuid();
 
        void Connect(object obj)
        {
            try
            {
 
                IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
                TcpClient client = new TcpClient();
                client.Connect(ep);
                string request;
                StringBuilder sb = new StringBuilder();
                using (NetworkStream stream = client.GetStream())
                {
                    request = obj.ToString() + '\0';
                    Console.WriteLine("Client: " + request);
 
                    stream.Write(Encoding.UTF8.GetBytes(request), 0, request.Length);
                    countServer = countServer + 1;
                    int i;
                    while ((i = stream.ReadByte()) != 0)
                    {
                        sb.Append((char)i);
                    }
                }
                client.Close();
 
                if (!request.Contains(guid.ToString()))
                {
                    Logfile.LogFile("Вернулось другое значение" + sb.ToString());
                }
 
                Console.WriteLine(sb.ToString());
 
 
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
 
        }
 
        void start()
        {
            using (var threadCount = new CountdownEvent(startCount))
            {
                for (int i = startCount; i > 0; i--)
                {
                    ThreadPool.QueueUserWorkItem(
                        x
                        =>
                        {
                            countClient = countClient + 1;
                            Connect((object)string.Format("Send iteration:{0}  --- " + guid + "", countClient));
                            threadCount.Signal();
 
                        });
                }
 
                /*        while (true)
                        {
 
                            string str = Console.ReadLine();
                            ThreadPool.QueueUserWorkItem(Connect, (object)str);
               }*/
                threadCount.Wait();
            }
            if (countClient == startCount)
            {
                Logfile.LogFile("Client[" + guid + "] - отправлено: [" + countClient.ToString() + "] - " + "пришло: [" + countServer.ToString() + "]");
            }
            else
            {
                Logfile.LogFile("Client[" + guid + "] - отправлено: [" + countClient.ToString() + "] - " + "пришло: [" + countServer.ToString() + "]");
            }
        }
 
 
        static void Main(string[] args)
        {
            Program p = new Program();
            p.start();
 
            Console.ReadKey();
        }
    }
}
Сервер
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
 
namespace server
{
    public class server
    {
        ManualResetEvent tcpClientConnected = new ManualResetEvent(false);
 
        void ProcessIncomingData(object obj)
        {
            try
            {
                TcpClient client = (TcpClient)obj;
                StringBuilder sb = new StringBuilder();
 
                using (NetworkStream stream = client.GetStream())
                {
                    int i;
                    while ((i = stream.ReadByte()) != 0)
                    {
                        sb.Append((char)i);
                    }
 
                    string reply = "Server: " + sb.ToString() + '\0';
                    //  stream.Write(Encoding.ASCII.GetBytes(reply), 0, reply.Length);
                    stream.Write(System.Text.Encoding.UTF8.GetBytes(reply), 0, reply.Length);
                }
                Console.WriteLine(sb.ToString());
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
 
        void ProcessIncomingConnection(IAsyncResult ar)
        {
            //Thread.Sleep(10000);
            TcpListener listener = (TcpListener)ar.AsyncState;
            TcpClient client = listener.EndAcceptTcpClient(ar);
 
            ThreadPool.QueueUserWorkItem(ProcessIncomingData, client);
            tcpClientConnected.Set();
        }
 
        public void start()
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
            TcpListener listener = new TcpListener(endpoint);
            listener.Start();
 
            while (true)
            {
                tcpClientConnected.Reset();
                listener.BeginAcceptTcpClient(new AsyncCallback(ProcessIncomingConnection), listener);
                tcpClientConnected.WaitOne();
            }
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            server s = new server();
            s.start();
        }
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.04.2017, 09:21
Ответы с готовыми решениями:

TCP/IP клиент-сервер
Подскажите пожалуйста, как реализовать взаимодействие клиентского и серверного приложения по протоколу TCP/IP, если работают они в разных...

TCP клиент-сервер
Есть у кого нибудь простой работающий пример TCP соединения клиент-сервер допустим для отправки сообщений выложите пожалуйста. ...

Потеря данных при передаче по TCP
Система сложная, отслеживает и записывает все происходящее. В итоге получается вот что: сервер отправляет пакет (условный фрагмент из байт)...

22
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
18.04.2017, 22:52
В многопоточной среде нужно делать синхронизацию доступа (чтения/записи) к общим ресурсам.
Для изменения значений переменных countClient, countServer используйте легковесную синхронизацию - Interlocked.Increment, тогда результат "сойдётся"
1
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 10:32  [ТС]
Добрый день, попробовал с данным методом проверить, потери все ровно имеются. Даже не знаю теперь в какую сторону думать.

1 Client[49d4d9c7-0b8f-487e-a83a-474d5226411d] - отправлено: [10000] - пришло: [6032]
1 Client[24963816-ea0a-4b23-82cc-427f59c845eb] - отправлено: [10000] - пришло: [5780]
1 Client[e91a4507-7ca2-4a18-8fea-2a2f551307e3] - отправлено: [10000] - пришло: [5230]
1 Client[b9b0389b-1373-4296-b507-70572abfb5b7] - отправлено: [10000] - пришло: [5006]
1 Client[8b84df0a-cc02-4496-b42c-2014f59a2f2e] - отправлено: [10000] - пришло: [5489]
1 Client[2ccffeb5-f92e-4e0c-a9ac-fd786c2ae560] - отправлено: [10000] - пришло: [5663]
1 Client[bcc3c382-e9b5-4277-8b49-ce5e5c483dc7] - отправлено: [10000] - пришло: [5421]
1 Client[2c1f25a5-c177-4d7d-93a3-2bd2927cdc02] - отправлено: [10000] - пришло: [5491]
1 Client[7acbeacf-22c6-4759-a318-4ec6472acd04] - отправлено: [10000] - пришло: [5531]
1 Client[95609929-9b0f-47ff-bf61-e20e105420b3] - отправлено: [10000] - пришло: [5667]
1 Client[5b736def-8192-40eb-8a98-eb9dc714b0d6] - отправлено: [10000] - пришло: [5547]
1 Client[8a286049-53c5-42d6-826a-d18f6c11b525] - отправлено: [10000] - пришло: [5584]
1 Client[2cc83782-4026-4a2d-9089-b14d08a8b9a9] - отправлено: [10000] - пришло: [5892]
1 Client[fc206b7b-2de8-4250-8526-2efe2973ec40] - отправлено: [10000] - пришло: [5609]
1 Client[46c2cfe4-5647-4e2e-8397-580da1393ec0] - отправлено: [10000] - пришло: [5643]
1 Client[0270d5ec-fee2-478b-a751-b2652bd46a14] - отправлено: [10000] - пришло: [5439]
1 Client[fe182221-ae9b-4413-bb12-8777e4df4b43] - отправлено: [10000] - пришло: [5564]
1 Client[32f9cc80-5c7e-4bb2-9c91-6b42fc09da5d] - отправлено: [10000] - пришло: [5934]
1 Client[203f65c1-abd9-4cc7-8959-df9f005a3514] - отправлено: [10000] - пришло: [6023]
1 Client[016c8c22-2a7a-40be-80eb-3112e165aebe] - отправлено: [10000] - пришло: [5860]
1 Client[c2b7de46-2b3b-4268-946f-3dbb45d71193] - отправлено: [10000] - пришло: [5760]
1 Client[955933c2-5530-447d-8073-1e9c761dd4b8] - отправлено: [10000] - пришло: [5835]
1 Client[ae1c48ba-064c-450a-b6b1-ea10dcaf5208] - отправлено: [10000] - пришло: [5947]
1 Client[e92d4b34-90db-45e8-bfcf-857b46da4dbe] - отправлено: [10000] - пришло: [5883]
1 Client[accdd529-e6a2-45b6-9c2e-60e4eb02480b] - отправлено: [10000] - пришло: [6287]
1 Client[85e45bee-e76e-4f06-a510-d84c90741706] - отправлено: [10000] - пришло: [6098]
1 Client[09654bcd-f4aa-43b7-8997-f8683d50b40f] - отправлено: [10000] - пришло: [6178]
1 Client[e6e3b71d-7b07-4172-afef-e4dc0f7a40d9] - отправлено: [10000] - пришло: [5766]
1 Client[94cfd8d5-8cc9-49f1-866a-88ab46f217d4] - отправлено: [10000] - пришло: [6036]
1 Client[9474029e-7356-4d8b-a509-f8decc66cf39] - отправлено: [10000] - пришло: [5915]
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
19.04.2017, 11:20
Попробовал запустить ваш код.
Без Interlocked примерно на 10-15 меньше : 9993/9983
С Interlocked: 10000/10000
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 12:32  [ТС]
Вы запускали один клиент или множество?

Я также проверил с Interlocked на более мощной машине, запустив одновременно 40 клиентов. Все данные успешно вернулись. Скорее всего это из-за железа и операционной системы.
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
19.04.2017, 14:01
Данные не могут просто так не вернуться, в любом случае вы получите какое то исключение либо при подключении либо при коммуникации. Например таймаут подключения, если сервер сильно загружен и не может ответить вовремя.
Для диагностики отключите на клиенте все логирование кроме catch Exception, так вместо "шума" увидите что с подключениями не так.
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 14:03  [ТС]
Мне выводит такое сообщение об ошибке
"Невозможно выполнить операцию на сокете, т.к. буфер слишком мал или очередь переполнена"
Все пересмотрел, так и не понял как с этим разобраться.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
19.04.2017, 16:47
вы шлете utf8 а читаете побайтно, пока не увидете 0. думаю загвоздка в этом т.к. в тексте может прилететь ноль на определенном символе.

Добавлено через 7 минут
Цитата Сообщение от SnakeLight Посмотреть сообщение
Logfile.LogFile("Client[" + guid + "] - отправлено: [" + countClient.ToString() + "] - " + "пришло: [" + countServer.ToString() + "]");
хм... а что вы этим вообще проверяете?!
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.04.2017, 16:47
Цитата Сообщение от Wolfdp Посмотреть сообщение
вы шлете utf8 а читаете побайтно, пока не увидете 0. думаю загвоздка в этом т.к. в тексте может прилететь ноль на определенном символе.
Да там еще и отправляется в UTF-8 а число байт берется из длины исходной строки, что естественно не будет совпадать для не ASCII символов.
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 16:48  [ТС]
Попробовал убрать stream(write и read) для проверки, выдает так же ошибку
"Невозможно выполнить операцию на сокете, т.к. буфер слишком мал или очередь переполнена"
при большом количестве клиентов.

Думаю либо пробовать при ошибки снова пытаться отправлять сообщение или искать какой то другой выход.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
19.04.2017, 16:54
Цитата Сообщение от SnakeLight Посмотреть сообщение
искать какой то другой выход.
использовать Read вместо ReadByte
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 17:20  [ТС]
Тут дело вовсе не в ReadByte. Убрав запись и чтение. Клиенту все ровно выводится данная ошибка, которую я писал выше.
Как понимаю при коннекте выводится ошибка

Добавлено через 12 минут
Данным сообщением
Logfile.LogFile("Client[" + guid + "] - отправлено: [" + countClient.ToString() + "] - " + "пришло: [" + countServer.ToString() + "]");
я проверяю сколько я отправил сообщений и сколько вернулось.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
19.04.2017, 17:43
Цитата Сообщение от SnakeLight Посмотреть сообщение
я проверяю сколько я отправил сообщений и сколько вернулось.
вот вообще ни разу. =) У вас countServer плюсуется после отправки, а не после чтения с сервера.

возможно валится на том факте, что сразу 10к подключений сервак принять не может
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
19.04.2017, 17:56  [ТС]
Согласен насчет подсчет с сервера. Но проблему оно не решает
Ошибка откуда-то появляется и как вариант остается дополнительный цикл добавлять на повтор отправки сообщения если вышла ошибка.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
19.04.2017, 20:08
нет, может конечно я и не прав, но подозреваю что нужно химичить с количество единовременых подключений
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
20.04.2017, 02:46
В общем чуть подправил код, запустил и... часть сообщений виснит на ReadByte. XD Заменил порт, вроде пошло дело, по крайне мере 1к отработало.
Nyan.TestTcp.Server.zip
1
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
20.04.2017, 09:34  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
В общем чуть подправил код, запустил и... часть сообщений виснит на ReadByte. XD Заменил порт, вроде пошло дело, по крайне мере 1к отработало.
Проверил у себя ваш проект, потери данных пропали, но вот отправляются по прежнему не все сообщения, если нужно отправить 5000 сообщений сразу 40 клиентам, то среднее значение отправленных сообщений получается ~3500
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
20.04.2017, 11:06
Цитата Сообщение от SnakeLight Посмотреть сообщение
5000 сообщений сразу 40 клиентам
как єто делаете?
0
 Аватар для SnakeLight
2 / 2 / 0
Регистрация: 23.09.2008
Сообщений: 54
20.04.2017, 11:20  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
как єто делаете?
Я решил проблему с отправкой сообщений, теперь ровно 5000 отправляет и 5000 приходят при 40 клиентах.

Как я использую одновременно 40 клиентов, да просто при помощи bat скрипта:

Bash
1
2
3
for /L %%A IN (1 1 40) DO (
start Client.exe -p
)
Ниже прикрепил файл проекта.
Вложения
Тип файла: rar Server.rar (48.8 Кб, 15 просмотров)
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
20.04.2017, 11:34
Цитата Сообщение от SnakeLight Посмотреть сообщение
Ниже прикрепил файл проекта.
не понял в чем различия от моего варианта. И да, Console.WriteLine("Попытка отправить сообщение заново..."); только выводит сообщение, заново ничего не отправляется.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.04.2017, 11:34
Помогаю со студенческими работами здесь

TCP клиент-сервер через интернет
Ситуация такая: Есть два компа. На одном сервер на другом клиент. Все реализована на TcpListener/TcpClient. Клиент передает на...

Клиент-сервер TCP через маршрутизатор
Пишу программу для сетевого взаимодействия клиент-сервер. Назначение - возможно чат. Писал на блокирующих сокетах TCP по документации...

Передача данных на удаленный сервер по TCP несколькими потоками
День добрый! Подскажите как лучше сделать, нкжно передавать данные на удалённый сервер по TCP, в один поток всё работает, вопрос как...

Клиент-сервер для ведения баз данных
Необходимо написать клиент-серверное приложение. Сервер принимает запросы и выдает информацию из баз. Как организовывать такое приложения?...

База данных (сервер - клиент)
Короче нужно реализовать такую тему. Программа запускается в ней уже введен ключ например 1123456 этот ключ отсылает на сервер сервер...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru