C套接字:send函数是否等待recv结束?

9
我在Windows上使用阻塞式C套接字。我使用它们来在服务器和客户端之间发送数据更新。我以高频率(每100毫秒)发送更新。当使用send()函数发送数据时,是否会等待接收方recv()接收数据才结束?
如果我理解手册正确的话,我认为不会:
"send()的成功完成不能保证消息传递。"
那么,如果一个人运行10个send()调用,而另一个人只完成了1个recv(),会发生什么?
我需要使用某种确认系统吗?

套接字的协议类型是什么?TCP,UDP还是其他什么? - torak
5个回答

15

假设您正在使用TCP协议。当您调用send时,发送的数据将立即放置在出站队列中,并且send操作将成功完成。但是,如果send无法将数据放置在出站队列中,则会返回错误。

由于TCP是一种保证交付的协议,只有在远程端确认接收到数据后,出站队列中的数据才能被删除。这是因为如果在规定时间内没有收到确认消息,则可能需要重新发送数据。

如果远程端响应缓慢,则出站队列将填满数据,而send操作将阻塞直到有空间将新数据放置在出站队列中。

然而,连接可能会以无法再发送任何进一步数据的方式失败。尽管一旦TCP连接已关闭,任何进一步的发送都将导致错误,但用户无法知道有多少数据实际上已经传输到另一端。(我不知道如何从套接字中检索TCP簿记到用户应用程序)。因此,如果需要确认数据的接收,您应该在应用程序级别上实现此功能。

对于UDP协议,可以毫不费力地说必须报告已经或未收到的数据。


11

send()会阻塞,直到操作系统(内核)将数据放入传出数据缓冲区中。它不会等待另一端接收数据。


2
如果你使用TCP协议发送数据,你可以得到保证交付1的服务,而且接收端会按照发送顺序接收数据。但是,这可能会将10个单独的更新作为单个大包一起接收(或反之亦然——单个更新可能会被分成任意数量的数据包)。这意味着,除其他外,任何数据的ACK都会隐式确认所有先前数据的接收。

如果你使用UDP协议,上述情况都不适用——数据可能会乱序到达,或者根本就会丢失。如果你关心所有的数据都能被接收,那你几乎需要在UDP之上构建自己的确认系统。

1当然,对于保证的限制也有一个限度——如果网络电缆被切断(或其他原因),数据包将无法传递,但你至少会收到一个错误消息告诉你连接已经丢失。


0

如果您正在使用TCP,则可以免费获得确认,因为这是协议在幕后执行的一部分。但是对于这种类型的应用程序,您可能希望使用UDP。无论哪种情况,send()都不会阻塞,直到客户端成功recv()

如果客户端接收每条消息至关重要,则使用TCP。如果客户端错过一条或多条消息没有问题,则使用UDP。


1
你可以在TCP层面上获得确认,但如果你需要在应用层面上获得确认,也就是说,如果你需要知道消息已经被接收,你需要在你使用的任何应用协议中实现确认。 - nos

0

TCP在较低的TCP协议栈层面上保证传递。它会重试传递,直到接收方确认已经接收到数据,但是您的应用程序可能永远不会知道这个事实。

假设您正在发送数据块,并且需要根据某些逻辑将这些数据块放置在某个位置。如果您的应用程序没有准备好知道每个单独块应该放置在哪里,那么在TCP层面接收它可能是无用的。原始帖子是关于应用程序级别的逻辑。


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