套接字通信中send()和recv()方法的行为

3
以下是设置:
服务器         客户端
 |                |
accept         connect
 |                |
 v                |
send msg1->       | 
 |                |
 v                v
recv    <-     send
 |                |
 v                v
send msg2->    recv
 |                |
 v                v
               close
这里是我的问题:
1. 客户端实际上在关闭之前接收到了消息1,为什么会这样?
2. 发送消息2返回正常。由于客户端在接收消息1后关闭,为什么发送消息2成功?
P.S. 我正在使用TCP的流套接字。

你正在使用数据报套接字吗?如果是这样,发送方实际上根本不知道是否有任何发送已经被接收到。 - msw
2个回答

5
  1. recv函数将获取接收缓冲区中的下一个内容。对于客户端而言,如果套接字是数据报套接字,则下一个内容是msg1。如果它是流套接字,则不会维护消息边界,因此如果msg2已到达且接收缓冲区有足够的空间,则recv可能包含来自msg1msg2的数据。

  2. send不等待另一端recv消息,它只是将其添加到发送队列中。在这个时候,它不知道客户端是否会在读取它之前关闭连接。如果您需要知道,您应该让客户端发送响应以确认收到消息。


为什么在调用recv()之前就收到数据了?我认为只有在send()完成后recv()才会被调用,但是服务器在send()完成之前就发送了msg1。 - gc .
1
TCP协议栈负责发送/接收数据。您不必调用recv()函数让操作系统接收数据 - 至少在操作系统的内部缓冲区未满之前不需要。请记住,TCP也是基于流而非消息的 - 一个send()调用可能需要多个recv()调用来接收数据,反之亦然。 - nos
1
当数据从网络到达时,操作系统会将其缓冲,直到应用程序调用recv()。此时可能已经到达了多个数据包,您的应用程序可以通过一次调用recv()获取所有数据。如果您不调用recv(),它将继续缓冲数据,直到接收窗口已满。然后,您必须调用recv()来为更多数据腾出空间。 - mark4o

4

在建立连接后,操作系统会管理进出您系统的数据包,recv()调用只是读取数据包缓冲区,而send()调用只是将数据包排队。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接