C socket:确实发送等待recv结束?

时间:2010-08-26 19:15:58

标签: c sockets networking tcp

我在Windows上使用阻塞C套接字。 我使用它们将数据的更新从服务器发送到客户端,反之亦然。我以高频率(每100毫秒)发送更新。 send()函数是否会等待收件人recv()在结束前收到数据?

如果我理解了这个手册页,我不会假设:

  

“send()的成功完成并不能保证传递信息。”

那么如果一个人发生了10 send()次发生而另一个只完成了1 recv()会发生什么?

我是否需要使用某种确认系统?

5 个答案:

答案 0 :(得分:11)

让我们假设您正在使用TCP。当您调用send时,您发送的数据会立即放在传出队列上,然后发送成功完成。但是,如果send无法将数据放在传出队列上,send将返回错误。

由于Tcp是保证传送协议,因此只有在远程端收到确认后,才能删除传出队列上的数据。这是因为如果没有及时收到确认,可能需要重新发送数据。

如果远程端缓慢,传出队列将填满数据,然后发送将阻塞,直到有空间将新数据放在传出队列上。

然而,连接失败的方式是无法再发送任何其他数据。虽然TCP连接一旦关闭,任何进一步的发送都将导致错误,用户无法知道实际上有多少数据到达另一方。 (我知道无法从套接字检索TCP簿记到用户应用程序)。因此,如果需要确认接收数据,则应该在应用程序级别实现此功能。

对于UDP,我认为不言而喻,某种方式报告已收到或未收到的内容是必须的。

答案 1 :(得分:8)

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

答案 2 :(得分:2)

如果您通过TCP发送,您将获得保证交付 1 ,另一端将按发送的顺序接收数据。但是,这可能会合并在一起,因此您发送的10个单独更新可以作为单个大数据包接收(反之亦然 - 单个更新可以在任意数量的数据包中分解)。这意味着,除其他外,任何数据的任何ACK都会隐式确认收到所有先前的数据。

如果您正在使用UDP,那么这些都不是真的 - 数据可能无序到达,或者被丢弃而根本无法传送。如果您关心所有收到的数据,您只需要在UDP本身之上构建自己的某种确认系统。

1 当然,保证是有限制的 - 如果网络电缆被切断(或其他)数据包将无法传送,但您至少会收到错误消息你连接丢失了。

答案 3 :(得分:0)

如果你正在使用TCP,你可以免费获得确认,因为这是协议所做的一部分。但听起来像这种类型的应用程序,你可能想要使用UDP。在任何一种情况下,send()都不会阻止,直到客户端成功recv()

如果客户端收到每条消息至关重要,那么请使用TCP。如果客户端可以错过一条或多条消息,则使用UDP。

答案 4 :(得分:0)

TCP保证在较低的TCP堆栈级别交付。它重试传递,直到接收部分确认已收到数据,但您的应用程序可能永远不知道该事实。

让我们假设您正在发送数据块,并且您需要根据某些逻辑将这些数据块放在某处。如果您的应用程序不准备知道每个块必须放在哪里,那么在TCP级别接收它可能是无用的。原帖是关于应用程序级逻辑的。