2010-04-06 2 views
3

Ниже установка:Поведение посыла() и RECV() в гнездо связи

Server   Client 
|    | 
accept   connect 
|    | 
v    | 
send msg1->  | 
|    | 
v    v 
recv <-  send 
|    | 
v    v 
send msg2-> recv 
|    | 
v    v 
       close

Вот мой вопрос:
1. Клиент фактически получает msg1 перед закрытием, почему это как это?
2. отправьте сообщение msg2 нормально. Поскольку клиент закрывается после получения msg1, почему сообщение успешно отправлено msg2?

P.S. Я использую потоковый сокет для TCP.

+0

Вы используете сокеты для дейтаграмм? Если это так, отправитель в буквальном смысле понятия не имеет, если какая-либо передача когда-либо получалась в любом месте. – msw

+0

Нет, я использую потоковое сокет. –

ответ

4
  1. Функция recv получит все, что будет дальше в буфере приема. В случае клиента, если сокет представляет собой сокет датаграммы, то следующий: msg1. Если это сокет потока, то границы сообщений не поддерживаются, поэтому recv может включать в себя данные от msg1 и msg2, если msg2 пришел и есть место для обоих в буфере recv.

  2. send не дожидается, пока другая сторона отправит recv сообщение, оно просто добавляет его в очередь отправки. В этот момент не известно, будет ли клиент закрывать соединение перед его чтением. Если вам нужно знать, что вы должны отправить клиенту ответ, чтобы подтвердить сообщение.

+0

Почему данные, полученные до вызова recv()? Я думаю, что recv() не вызывается до тех пор, пока send() не завершится, но msg1 отправляется сервером перед отправкой(). –

+1

TCP-стек позаботится о передаче/приеме данных. вам не нужно вызывать recv() для ОС для получения данных - по крайней мере, пока внутренние буферы ОС не будут заполнены. Имейте в виду, что TCP также основан на потоке, а не на ориентированном на сообщения - для вызова one() может потребоваться несколько вызовов recv() для приема и наоборот. – nos

+1

Когда данные поступают из сети, ОС буферизует ее до тех пор, пока ваше приложение не вызовет 'recv()'. К этому моменту, возможно, поступило несколько пакетов, и ваше приложение может сразу получить все данные с помощью одного вызова 'recv()'. Если вы не вызываете 'recv()', он будет буферизировать данные до тех пор, пока окно приема не будет заполнено. Затем вам нужно будет вызвать 'recv()', чтобы освободить место для большего количества данных. – mark4o

4

После того как соединение установлено, ОС управляет пакеты на входе и выходе системы, вызов RECV() просто считывает буфер пакетов и посыла вызова() только очереди пакетов.