Сбросить сокет в C++

Я попытался очистить сокет после вызова функции send в C++.
Я использовал библиотеку winsock2.h.

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

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

Итак, как я могу это сделать?


person nrofis    schedule 10.10.2012    source источник
comment
Вы можете проверить этот предыдущий пост или просмотреть Документация MSDN относительно того же   -  person AurA    schedule 10.10.2012
comment
Если сокет TCP, то первое, что нужно сделать, это отключить алгоритм Nagle.   -  person bobah    schedule 10.10.2012
comment
Если вам не нужно больше ничего делать в сокете, то его закрытие очистит его (если в параметрах сокета не установлено задержка).   -  person Rudolfs Bundulis    schedule 10.10.2012
comment
@bobah здесь FAQ по отключению Nagle tangentsoft.net/wskfaq/intermediate.html# отключить-нагле   -  person Sergei Nikulov    schedule 10.10.2012
comment
@Сергей - не знаю, почему ты адресовал свой комментарий мне, но спасибо. Если вы подразумеваете, что отключение алгоритма Nagle — плохая идея, то я могу ответить только правильным инструментом для правильной задачи, алгоритм Nagle отключен в большинстве программ для обмена сообщениями с малой задержкой.   -  person bobah    schedule 10.10.2012


Ответы (5)


Вы ничего не можете сделать на стороне отправки, чтобы заставить сторону получать получать сообщения "одно за другим". Ответственность за правильное восстановление отправленных кадров («сообщений») полностью лежит на принимающей стороне. Код приема должен знать длину сообщения каким-то образом (полностью зависящим от протокола) и получать столько данных, сколько необходимо для создания всего кадра (обычно это достигается путем отправки recv с указанной длиной и указанными, которые интересны только для весь буфер, например, флаг MSG_WAITALL). Мне очень трудно поверить, что ваше устройство не знает, как с этим справиться, и если это действительно так, вы буквально ничего не можете сделать. Я считаю более вероятным, что вы не понимаете требования к устройству/протоколу и задаете неправильный вопрос.

person Remus Rusanu    schedule 10.10.2012

Для сокетов нет функциональности «flush». Если вам нужно отправить два сообщения в быстрой последовательности, просто отправьте их. Если это сокет TCP, то они прибудут в правильном порядке (в том порядке, в котором вы их отправляете).

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

person Some programmer dude    schedule 10.10.2012
comment
Я отправляю сообщение на устройство, и оно принимает одно сообщение за раз. - person nrofis; 10.10.2012
comment
Даже если вы отправили все данные, которые у вас были, нет гарантии, что они придут сразу. - person M4rc; 10.10.2012
comment
@Someone Вы имеете в виду, что стек TCP / IP на принимающей стороне имеет буфер, достаточный только для одного отдельного сообщения? Или что принимающая программа есть? В любом случае, это не проблема при использовании TCP, так как TCP может справиться с этим. - person Some programmer dude; 10.10.2012
comment
@Someone Какой внутренний буфер? Не могли бы вы отредактировать свой вопрос, включив в него некоторый код (или, по крайней мере, псевдокод), чтобы показать, что вы делаете? Как на стороне отправителя, так и на стороне получателя? - person Some programmer dude; 10.10.2012
comment
Получатель - это устройство, а отправитель - компьютер, я просто хочу отправить сообщение на устройство. Единственная проблема заключается в том, что устройство может получать одну команду за раз. - person nrofis; 10.10.2012
comment
@Someone А ты пробовал? большинство всех программ, получающих сообщения, получают по одному сообщению за раз, выполняют некоторую обработку, а затем пытаются получить следующее сообщение. Вы не очень хорошо описываете свою проблему, поэтому я и попросил код. И то, что приемник является устройством, не имеет значения, если только это не очень маленькое устройство (т. е. объем ОЗУ исчисляется однозначным или двузначным числом килобайт). - person Some programmer dude; 10.10.2012
comment
Конечно, я проверил это, я использовал сниффер, чтобы увидеть весь сетевой трафик, и я увидел, что мои сообщения отправляются вместе, и устройство их не распознает. Извините за запутанный вопрос. - person nrofis; 10.10.2012
comment
@Someone Тогда вам нужно изменить свой протокол для разделения сообщений. Либо добавьте заголовок, содержащий размер сообщения, либо используйте специальный разделитель, которого никогда не может быть в сообщениях. Это не проблема с коммуникационным или сетевым стеком, а проблема, связанная исключительно с протоколом. - person Some programmer dude; 10.10.2012

Точный ответ на ваш вопрос о схеме пакетов с примером из Часто задаваемые вопросы по Winsock

person Sergei Nikulov    schedule 10.10.2012

Насколько мне известно, на самом деле не существует способности «флеш». функция отправки возвращает количество отправленных байтов, поэтому вы можете повторять цикл до тех пор, пока не будут отправлены все байты.

Изменить: чтобы добавить к тому, что я прочитал, вы хотите от других пользователей. Единственный известный мне способ увеличить «внутренний буфер» (очистка его — это то, что winsock делает сам по себе) — это setsockopt с использованием параметра so_sendbuf.

Статья о нем:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740476%28v=vs.85%29.aspx

person M4rc    schedule 10.10.2012
comment
Я не хочу увеличивать его, я просто хочу отправить свое сообщение сразу после вызова функции отправки. Я не хочу, чтобы сообщение ждало в буфере сокета. - person nrofis; 10.10.2012
comment
Помимо выключения winsock, нет способа сбросить его. И даже это не гарантирует его смыва. Мой вариант устраняет проблему, которая у вас была с внутренним буфером. Тем не менее, теоретически вы можете сделать его крошечным, чтобы попытаться обманом отправить его раньше, но опять же, это не гарантирует работу. - person M4rc; 10.10.2012

установите для параметров сокета значение NDELAY на стороне отправки

person Steve Ried    schedule 18.02.2016