Скорость отправки TCP-сокета C ++

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

И вот что я получаю (пример):

Bytes Sent:  217, Time:  34.3336 usec
Bytes Sent:  217, Time:   9.9107 usec
Bytes Sent:  226, Time:  20.1754 usec
Bytes Sent:  226, Time:  38.2271 usec
Bytes Sent:  217, Time:  33.6257 usec
Bytes Sent:  217, Time:  12.7424 usec
Bytes Sent:  217, Time:  21.5912 usec
Bytes Sent:  217, Time:  31.1480 usec
Bytes Sent:  218, Time:  28.3164 usec
Bytes Sent:  218, Time:  13.0963 usec
Bytes Sent:  218, Time:  82.8254 usec
Bytes Sent:  218, Time:  13.0963 usec
Bytes Sent:  227, Time:  30.7941 usec
Bytes Sent:  218, Time:  27.9624 usec
Bytes Sent:  216, Time:   2.1237 usec
Bytes Sent:  218, Time:  12.3884 usec
Bytes Sent:  227, Time:  31.1480 usec
Bytes Sent:  227, Time:  88.4887 usec
Bytes Sent:  218, Time:  93.0901 usec
Bytes Sent:  218, Time:   7.7870 usec
Bytes Sent:  218, Time:  28.3164 usec
Bytes Sent:  227, Time:  89.5505 usec
Bytes Sent:  218, Time:  84.2412 usec
Bytes Sent:  218, Time:  13.8042 usec
Bytes Sent:  227, Time:  99.4612 usec
Bytes Sent:  218, Time:  86.0110 usec
Bytes Sent:  218, Time:  12.3884 usec
Bytes Sent:  218, Time:  87.7807 usec
Bytes Sent:  216, Time:   3.5395 usec
Bytes Sent:  218, Time:   4.6014 usec
Bytes Sent:  218, Time:  36.1034 usec
Bytes Sent:  218, Time:  14.8661 usec
Bytes Sent:  218, Time:  24.0689 usec
Bytes Sent:  218, Time:  18.0517 usec
Bytes Sent:  227, Time:  24.4229 usec

Кто-нибудь знает, почему это может произойти? Почему для одного сообщения отправляется 3 пользователя, а для другого 80?
И есть ли способ это исправить?

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

Некоторые дополнительные детали относительно того, что я делаю:

C ++, Visual Studio 2013

Как я открываю:

...
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
...
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
...

Как я отправляю и рассчитываю время:

...
LARGE_INTEGER cT;
QueryPerformanceCounter(&cT);
long long dT = cT.QuadPart;

iBytesSent = send(ConnectSocket, msgFinal, msgFinalLen, 0);

QueryPerformanceCounter(&cT);
dT = cT.QuadPart - dT;
...

Также я слушаю этот сокет из другого потока, я не знаю, может ли это повлиять на отправку или нет:

iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0);

4

Решение

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

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

3

Другие решения

Вы не измеряете время, которое требуется для «отправки» сообщения, вы измеряете время, необходимое для того, чтобы сообщение было отправлено в буфер отправки TCP. Это может включать выделение памяти, конфликт блокировок и многое другое. Он также может включать в себя другой запланированный процесс, который приведет к потере времени.

1

То, что вы измеряете, это количество времени, которое занимает отправка вызова.
По сути, это операция записи (ввода / вывода) в буфер на уровне сокетов.

Ваш процесс пытается выполнить ввод-вывод и блокируется — после завершения ввода-вывода демон просыпается. Разница во времени для отправки вызовов включает в себя:

я. Фактическое время записи.

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

Твики:

я. Попробуйте оптимизировать размер окна отправки / получения. Это количество данных, которое можно отправить без ожидания подтверждения.

Визит: Настройка окна получения TCP в C и работа с tcpdump в Linux

II. Буферы, которые вы передаете для отправки вызова, должны соответствовать размеру окна. Таким образом, tcp не ждет, пока ОПТИМАЛЬНЫЙ размер не будет достигнут, прежде чем фактически сбросить данные в сети.

III. Флаг, подобный TCP_NODELAY для реализации вашей ОС, поможет.

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

0
По вопросам рекламы [email protected]