异步接收是否可以在不读取我要求的所有字节的情况下返回?

时间:2009-06-09 13:13:26

标签: sockets asynchronous

我正在阅读有关如何使用异步套接字传输可变长度消息的an article on Vadym Stetsiak's blog

他说:

  

多条消息到达服务器时会发生什么?   在处理多个消息时,必须记住接收操作可以返回从网络读取的任意数量的字节。通常,该大小在Receive或BeginReceive方法中从0到指定的缓冲区长度。

所以,即使我告诉BeginReceive读取100个字节,它可能读取少于那个并返回??? 我正在开发一个支持网络的软件(TCP / IP),我总是收到与我要求的完全相同的字节数。

我甚至不理解逻辑:如果没有得到我要求的每个字节,为什么接收会异步完成...只是等待。

可能它与IP与TCP有关吗?

3 个答案:

答案 0 :(得分:2)

如果一个套接字在异步模式下运行,那么它将返回它当时实际拥有的任何字节,最多为所请求的数量,但可以(并且通常是)小于任何给定的请求数量读。您无法保证每次都获得所需的字节数。你必须反复阅读,直到你最终得到你需要的所有字节,然后缓存剩下的东西,以便稍后可以处理更多字节时处理它。这正是Vadym的示例代码正在做的事情。这种类型的读取是异步的,因为它在后台继续执行其他操作时接收套接字,然后在有更多字节可用时通知您。

您在想的是套接字在同步模式下的作用。在允许代码继续工作之前,它等待所有请求的字节到达。

答案 1 :(得分:0)

当以太网帧到达时,以太网设备驱动程序将整个帧复制到其内存,只有在复制整个帧后,它才会通知上层(TCP)。然后,TCP层将数据复制到其缓冲区并调用套接字层。然后,套接字层将可用数据复制到称为套接字缓冲区的缓冲区空间。最后,数据被复制到用户缓冲区,并发出信号。

receive()返回的数据大小可能小于请求的数据的情况是什么 - 1)如果以太网帧小于请求的大小 2)如果TCP缓冲区大小(系统范围大小,可以检查linux中的sysctl参数-net.ipv4.tcp_rmem)小于请求的大小。 3)如果套接字缓冲区大小(特定于应用程序的大小,可以使用SO_RCVBUF由setsockopt()设置)小于请求的大小。

除了上述情况之外,如果指定的用户缓冲区大小足以容纳整个帧,则整个帧将始终复制到用户缓冲区。

IP层在此处没有任何角色。

答案 2 :(得分:0)

是的,这确实是一种奇怪的行为。但是,这就是我看到它的方式......它可能是错的,但这是我在经过长时间的调试会议后向自己解释的方式: - /

当您使用正常接收(同步)时,它读取n个字节而不是返回..罚款。 当您使用BeginReceive(异步)时,它会在开始时调用您来读取n个字节。

所以,换句话说,它确实尝试读取n个字节..它只是告诉你何时开始接收它们而不是它何时结束。然后,有时候,读取n个字节是不可能的,但不幸的是,你的开始信号已被调用。

我同意你的看法,这个名字很混乱。

祝你好运!