socket通信中send()和recv()的行为
Posted
技术标签:
【中文标题】socket通信中send()和recv()的行为【英文标题】:The behavior of send() and recv() in socket communication 【发布时间】:2011-02-04 19:48:22 【问题描述】:以下是设置:
服务器客户端 | | 接受连接 | | v | 发送 msg1-> | | | v v 接收 recv | | v v 关闭
这是我的问题: 1.客户端实际上在关闭之前就收到了msg1,为什么会这样? 2.发送msg2正常返回。既然client收到msg1就关闭了,为什么send msg2成功了?
附:我正在为 TCP 使用流套接字。
【问题讨论】:
你在使用数据报套接字吗?如果是这样,发件人根本不知道是否在任何地方收到过任何发送。 【参考方案1】:recv
函数将获取接收缓冲区中的下一个内容。在客户端的情况下,如果套接字是一个数据报套接字,接下来是msg1。如果它是一个流套接字,则不维护消息边界,因此如果 msg2 已经到达并且在那里,recv 可以包含来自 msg1 和 msg2 的数据在 recv 缓冲区中有两个空间。
send
不等待对方发送recv
消息,它只是将其添加到发送队列中。那时它不知道客户端是否会在读取连接之前关闭它。如果您需要知道应该让客户端发送响应以确认消息。
【讨论】:
为什么在调用recv()之前收到了数据?我认为在 send() 完成之前不会调用 recv(),但是在 send() 完成之前由服务器发送 msg1。 TCP 栈负责发送/接收数据。您不必为操作系统调用 recv() 来接收数据 - 至少直到操作系统的内部缓冲区已满。请记住,TCP 也是基于流的,而不是面向消息的 - 一次 send() 调用可能需要多次 recv() 调用才能接收,反之亦然。 当数据从网络到达时,操作系统会对其进行缓冲,直到您的应用程序调用recv()
。到那时可能已经有几个数据包到达,您的应用程序可以通过一次调用recv()
一次获取所有数据。如果您不调用recv()
,它将继续缓冲数据,直到接收窗口已满。然后您必须致电recv()
为更多数据腾出空间。【参考方案2】:
建立连接后,操作系统会管理进出系统的数据包,recv() 调用只是读取数据包缓冲区,而 send() 调用只是对数据包进行排队。
【讨论】:
以上是关于socket通信中send()和recv()的行为的主要内容,如果未能解决你的问题,请参考以下文章