提问人:Sean Lynes 提问时间:9/21/2022 更新时间:9/23/2022 访问量:124
Winsock2 同步 IO...在 WSAGetOverlappedResult 中使用 fWait==TRUE 等待 WSASend “完成”
Winsock2 synchronous IO...waiting for WSASend to "complete" using fWait==TRUE in WSAGetOverlappedResult
问:
我和一位同事对 WSASend 重叠 IO 请求的“完成”存在分歧。他断言,在 WSAGetOverlappedResult 调用中使用 fWait 作为 TRUE 只会等到消息排队等待发送。他认为等待写入/发送操作“完成”仅意味着消息已成功启动。在我看来,这远非向插座另一端发送的“完成”消息......那只是发送的开始,而不是完成。如果 TRUE 的 fWait 在字节被发送并被 ACK(或返回错误)之前没有阻塞,那么这远非同步......事实上,它的作用与异步 IO 相同,因为它只是一劳永逸。
几十年来,我一直在维护我们公司的通信库,了解如何做以及什么是“同步”IO,所以如果我的理解确实错了,我会感到震惊。但我的同事是一位才华横溢的开发人员,拥有大量的 TCP/IP 经验,并且坚持认为他是对的。他说他甚至在stackoverflow上提出了这个问题,并被告知他是对的。我无法想象我怎么会误解发送的“完成”意味着除了发送请求的字节确实已发送和接受之外的任何事情。但是我之前错了,哈哈
所以。。。谁是对的?等待 WSASend 请求“完成”到底是什么意思?只需等待消息排队等待在 TCP/IP 堆栈中发送...或者等待构成消息的所有数据包被发送和接收???还是真相介于两者之间?
答:
你错了。
当不再处理发送请求时,发送请求即告完成。堆栈接管操作后,将不再处理请求,其资源可用于其他目的。
如果你是对的,重叠的 I/O 几乎毫无用处。谁愿意等到另一方完整地确认了之前的发送,然后才能将更多的数据排队到 TCP 连接?
如果无法确定排队过程何时完成,重叠的 I/O 有什么用处?这就是应用程序需要知道的内容,以便它可以发送另一个数据块。
您总是有死区时间,因为发送队列总是必须完全清空,然后才能在发送端排队更多数据。呸!
无论如何,知道何时收到 ACK 是没有用的。这并不意味着另一端的应用程序获得了数据。所以它在应用层没有意义。知道发送已经排队在应用层确实有意义 - 这意味着您现在可以将更多要发送的数据排队,并保证上一次发送的所有数据都将在下一次发送的任何数据之前传递到接收方的应用层。这就是应用程序需要知道的。
当发送排队时,对 WASSend 的同步调用也会完成。异步操作只是意味着您不必等待同步操作中等待的任何内容。所以这是你的理解会很奇怪的另一个原因。
最后,没有标准或通用的方法来等待具有同步操作的远程 ACK。因此,您必须认为异步操作默认提供语义,而同步操作甚至无法真正使用同步操作。这也很奇怪。
评论
大卫是对的。
当数据被移交给TCPIP堆栈(缓冲在其层上)时,WSASend将完成,以便在传输允许时发送。如果是阻塞呼叫,它将等到准备好挂起;就像它是异步的一样,OVERLAPPED I/O 将在挂起后完成。
有人可能会问,为什么这甚至是必要的?此行为对于通过 TCP 连接保持尽可能多的数据传输至关重要。为了在传输中保留尽可能多的数据,发送方应该调用 WSASend 直到它挂起(回想一下,如果它是同步 WSASend 调用,那么该线程将一直阻塞,直到 WSASend 可以完成;如果它是异步的,则一旦 WSASend 调用可以挂起,就会发生异步完成)。
为什么WSASend会挂起,为什么不立即完成?WSASend 只有在传输(在内核中)准备好缓冲更多数据时才会完成。因此,循环直到 WSASend 挂起将使该连接保持足够的数据,以保持最大数据在传输中。
希望这是有道理的。
评论
My testing seems to show I am indeed wrong. Synchronous behavior does not exist for sending...just receiving. I see how this is a performance help, but I object to all documentation saying sending fWait of TRUE in WSAGetOverlappedResult will wait until the IO request is "complete". This word implies much more than just it being queued up. Well..I'm flabbergasted that my understanding was off...but TCP handles things well enough that it hasn't caused me issues before.
Thanks for the excellent replies and patience with my frustrated replies. I'm incredibly disappointed at how all the documentation is written using words that would imply my understanding was right...when all along waiting for IO to "end", "complete", "finish" absolutely does NOT wait.
评论