2015-08-18 3 views
4

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

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

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 usec для отправки и для других 80 usec?
И есть ли способ исправить это?

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

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

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; 
... 

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

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

TCP - это протокол потока. В нем нет понятия «сообщения», вы отправляете поток байтов. Это означает, что получатель может получать данные в кусках разных размеров, чем то, что вы их отправляете, например. TCP только гарантирует, что другая сторона получает одни и те же байты в том же порядке, ничего не теряется (или происходит отключение, если resends fail). – hyde

+3

Я не думаю, что вы измеряете время отправки, вы измеряете время вызова 'send'. – Dariusz

+0

также устанавливает TCP_NODELAY, если вы хотите, чтобы ваше сообщение отправлялось так быстро, как вы можете. https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476%28v=vs.85%29.aspx –

ответ

3

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

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

+0

Есть ли способ контролировать и контролировать то, что было отправлено, и что находится в буфере? Может быть, есть какие-либо рекомендации/варианты/конфигурации, которые я могу указать, чтобы сделать процесс отправки более быстрым и стабильным? Или, может быть, это поможет увеличить размер буфера, если это возможно? :) – Artem

+1

@Artem Существует простой способ - не используйте TCP. TCP - это протокол потока, и у него есть некоторые гарантии и недостатки, которые вы найдете назойливыми, если попытаетесь использовать его для отправки быстрых небольших пакетов данных. UDP может быть лучшим выбором (хотя вы, вероятно, захотите использовать некоторую библиотеку более высокого уровня, чтобы справиться с этим). Но забудьте о * микро * секундах. В любом разумном сценарии вы все еще смотрите * миллисекунды секунд - едва ли можно пройти за миллисекунду в хорошо спроектированной локальной сети, но совершенно глупо по Интернету. – Luaan

+0

@Artem ** Я уже предложил правильную методологию. ** Что есть или нет в буфере, не имеет значения. – EJP

1

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

0

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

Ваш процесс пытается войти в систему и заблокирован - после того, как i/o завершает демон, проснулся. Разница во времени для отправки звонков включает в себя:

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

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

Твиты:

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

визит: Setting TCP receive window in C and working with tcpdump in Linux

II. Буферы, которые вы передаете на вызов отправки, должны соответствовать размеру окна. Таким образом, tcp не дожидается, пока не будет достигнут размер OPTIMUM до фактического удаления данных в сети.

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

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

+0

Спасибо, Я хотел бы уточнить один пункт. «iv. Отрегулируйте хорошее значение для вашего демона, чтобы оно проснулось, как только завершится вызов блокирующего ввода-вывода». Не могли бы вы объяснить, что означает «Подтвердить хорошее значение» и как эта «корректировка» может быть выполнена? – Artem

+0

Посетите: http://stackoverflow.com/questions/7618291/difference-between-nice-and-setpriority-in-unix. Это поможет привлечь внимание планировщика. – Abhinav

Смежные вопросы