2016-09-25 5 views
1

SORRY ДЛЯ BAD ENGLISHWeird поведение Send() и RECV()

Почему, если у меня есть два send() -s на сервере, а также два recv() -s на клиенте, иногда первый recv() получит содержимое 2-го send() с сервера, не беря только содержимое первого, и пусть другой recv() возьмет «надлежащее и правильное» содержимое другого send()?

Как я могу получить эту работу другим способом?

ответ

1

Это по дизайну.

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

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

Если вы отправляете 100 байт, а затем еще 100 байт, вполне возможно, что приемник вместо этого увидит 200 одновременно или даже 50 + 150 в двух разных командах чтения. Если вам нужны границы сообщений, вы должны сами поместить их в данные.

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

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

+0

Но как я могу сказать второй 'send()', чтобы ничего не отправлять первому 'rec()'? Ваше решение hellp меня с тем, что «текст 2» из «send() 2» не смешивается с «текстом 1», принятым в 'recv() 1'. Но потом я теряю данные 'send() 2', потому что его отправлено, и никто не ждет, чтобы он взял текст из отправленного. как я могу синхронизировать между точным отправлением и точным recv? –

+0

@dfsfg вы не можете. Вот в чем смысл этого ответа. Эти функции не работают. –

0

Скорее всего, вы используете гнездо типа SOCK_STREAM. Это TCP-сокет, и это означает, что вы выталкиваете данные в одну сторону и получаете с другой стороны в том же порядке и без пропущенных фрагментов, но нет разделителей. Таким образом, send() просто отправляет данные, а recv() получает все данные, доступные на текущий момент.

Вы можете использовать SOCK_DGRAM, а затем использовать UDP. Но в таком случае каждый send() отправит дейтаграмму, и recv() получит его. Но вам не гарантировано, что ваши датаграммы не будут перетасованы или потеряны, поэтому вам придется самому решать такие проблемы. Также существует ограничение на максимальный размер дейтаграммы.

Или вы можете придерживаться TCP-соединения, но тогда вам нужно отправлять разделители самостоятельно.

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