2010-08-26 93 views
6

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

我认为不是我的理解以及手册页:

“发送成功完成()并不能保证邮件的传递。”

如果一个正在运行10个send() OCCURENCES而另一只具有完整的1 recv()那么会发生什么?

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

+0

什么是套接字的协议类型? TCP,UDP还有其他的东西? – torak 2010-08-26 19:18:09

+0

我使用TCP协议 – Giann 2010-08-26 19:44:24

回答

10

让我们假设您使用的是TCP。当您呼叫发送时,您发送的数据立即被放置在传出队列中并发送,然后成功完成。但是,如果发送无法将数据放在传出队列上,发送将返回一个错误。

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

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

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

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

7

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

0

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

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

+1

您可以在TCP层上进行配置,但是如果您需要在应用层上进行配置,那么这并不会对您有所帮助,例如,如果您需要知道已收到消息,则需要在任何应用程序中实施ack你正在使用的协议。 – nos 2010-08-26 19:34:37

2

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

如果您使用的是UDP,那么这些都不是真的 - 数据可能不按顺序到达,或者被丢弃,并且根本不会传送。如果你关心所有收到的数据,你只需要在UDP本身之上建立你自己的确认系统。

当然,还有对担保的限制 - 如果网络电缆被削减(或其他)数据包将不会被发表,但你至少可以得到一个错误信息,告诉您连接丢失了。

0

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

假设您正在发送数据块,并且需要根据某种逻辑将这些数据块放在某处。如果您的应用程序不准备知道每个块的放置位置,则在TCP级别接收它可能没有用处。原帖是关于应用程序级别的逻辑。