简体   繁体   English

Winsock2 同步 IO ...等待 WSASend 在 WSAGetOverlappedResult 中使用 fWait==TRUE “完成”

[英]Winsock2 synchronous IO...waiting for WSASend to "complete" using fWait==TRUE in WSAGetOverlappedResult

A coworker and I are having a disagreement on what constitutes "completion" of a WSASend overlapped IO request.我和一位同事对 WSASend 重叠 IO 请求的“完成”构成存在分歧。 He asserts using fWait as TRUE in the WSAGetOverlappedResult call only waits until the message is queued for sending.他断言在 WSAGetOverlappedResult 调用中使用 fWait 为 TRUE 只会等到消息排队等待发送。 He believes waiting for the write/send operation to "complete" only means the message was successfully initiated.他认为等待写/发送操作“完成”仅意味着消息已成功启动。 In my opinion that is far from a "completed" message to the other side of the socket...that would simple be a beginning of a send and not a completion.在我看来,这远不是到套接字另一侧的“完成”消息......这只是发送的开始而不是完成。 If the fWait of TRUE does not block until the bytes have been sent and been ACKed (or error returned), then this is far from synchronous...it would in fact be acting the same as asynchronous IO because it's just fire and forget.如果 TRUE 的 fWait 在字节被发送并被确认(或错误返回)之前没有阻塞,那么这远非同步......它实际上与异步 IO 相同,因为它只是触发并忘记。

I have been maintaining our company's communication library with my understanding of how to do, and what is, "synchronous" IO for decades so I'll be shocked if I'm indeed wrong in my understanding.几十年来,我一直在维护我们公司的通信库,了解如何做以及什么是“同步”IO,所以如果我的理解确实错了,我会感到震惊。 But my coworker is a brilliant developer with TONS of TCP/IP experience and is adamant he's right.但我的同事是一位出色的开发人员,拥有大量 TCP/IP 经验,并且坚信他是对的。 Says he even posed this question here on stackoverflow and was told he was right.说他甚至在 stackoverflow 上提出了这个问题,并被告知他是对的。 I can't imagine how I could be misunderstanding "completion" of a send to mean anything other than the sending of the bytes requested were indeed sent and ACKed.我无法想象我怎么会误解发送的“完成”来表示除了发送请求的字节之外的任何内容确实已发送和确认。 But I've been wrong before LOL但是在LOL之前我错了

So...who is right?那么……谁是对的? What EXACTLY does it mean to wait for a WSASend request to be "complete"?等待 WSASend 请求“完成”到底意味着什么? Simply waiting until the message is queued for sending in the TCP/IP stack...or waiting for all the packets that constitute the message to be both sent and ACKed???只是等到消息在 TCP/IP 堆栈中排队等待发送......或者等待构成消息的所有数据包都被发送和确认??? Or is the truth somewhere in-between?还是介于两者之间的真相?

You are wrong.你错了。

A send request is completed when the request is no longer being processed.当不再处理请求时,发送请求完成。 Once the stack has taken over the operation, the request is no longer being processed and its resources can be used for some other purpose.一旦堆栈接管了操作,请求就不再被处理,它的资源可以用于其他目的。

If you were right, overlapped I/O would be nearly useless.如果你是对的,重叠的 I/O 几乎没有用。 Who would want to have to wait until the other side ACKed a previous send in its entirety before they could queue any more data to the TCP connection?谁愿意等到对方完全确认了先前的发送,然后才能将更多数据排队到 TCP 连接?

How would overlapped I/O be useful if there was no way to determine when the queing process was complete?如果无法确定排队过程何时完成,重叠 I/O 将如何发挥作用? That's what the application needs to know so it can send another chunk of data.这是应用程序需要知道的,以便它可以发送另一块数据。

You would always have dead time as the send queue would always have to get completely empty before more data could be queued on the sending side.总是会有死区时间,因为发送队列总是必须完全为空,然后才能在发送端排队更多数据。 Yuck!呸!

And knowing when the ACK is received is useless anyway.无论如何,知道何时收到 ACK 是没有用的。 It doesn't mean the application on the other end got the data.这并不意味着另一端的应用程序获得了数据。 So it has no meaning at application layer.所以它在应用层没有意义。 Knowing that the send has been queued does have meaning at application layer -- it means you can now queue more data to be sent and be guaranteed that all of the data from the previous send will be passed to the receive's application layer before any data from the next send.知道发送已排队在应用层确实有意义——这意味着您现在可以排队更多要发送的数据,并保证来自先前发送的所有数据将在来自任何数据之前传递到接收的应用层下一次发送。 What's what the application needs to know.应用程序需要知道什么。

A synchronous call to WASSend also completes when the send is queued.当发送排队时,对 WASSend 的同步调用也会完成。 An asynchronous operation just means you don't have to wait for whatever you'd wait for in a synchronous operation.异步操作只是意味着您不必等待您在同步操作中等待的任何内容。 So that's another reason your understanding would be quite strange.所以这是你的理解会很奇怪的另一个原因。

Lastly, there is no standard or common way to wait for a remote ACK with synchronous operations.最后,没有标准或通用的方法来等待具有同步操作的远程 ACK。 So you would have to think that asynchronous operations default to providing a semantic that is not even really available with synchronous ones.因此,您必须认为异步操作默认提供的语义甚至不能用于同步操作。 That's also pretty strange.这也很奇怪。

David is correct.大卫是对的。

WSASend will complete when that data is handed off to the TCPIP stack (buffered at their layer) to be sent whenever the transport will allow. WSASend 将在该数据被移交给 TCPIP 堆栈(在其层缓冲)以在传输允许时发送时完成。 If it's a blocking call, it will wait until it's ready to pend;如果是阻塞调用,它会等到准备好挂起; just like if it's async, the OVERLAPPED I/O will complete once it pends.就像它是异步的一样,OVERLAPPED I/O 一旦挂起就会完成。

Some may ask why is this even necessary?有人可能会问,为什么这甚至是必要的? This is behavior is crucial for keeping as much data in-flight over a TCP connection.这种行为对于通过 TCP 连接保持尽可能多的数据传输至关重要。 In order to keep as much data in-flight, a sender should call WSASend until it pends (recall if it's a synchronous WSASend call then that thread will just block until WSASend can complete; if it's asynchronous, the async completion will occur once that WSASend call can pend).为了保持尽可能多的数据在传输中,发送者应该调用 WSASend 直到它挂起(回想一下,如果它是一个同步的 WSASend 调用,那么该线程将阻塞直到 WSASend 可以完成;如果它是异步的,则异步完成将在 WSASend 发生后发生通话可以挂起)。

Why would WSASend ever pend, why not just complete immediately?为什么 WSASend 会挂起,为什么不立即完成? WSASend will only complete once the transport (in kernel) is ready to buffer more data.只有在传输(在内核中)准备好缓冲更多数据时,WSASend 才会完成。 So looping until WSASend pends will keep that connection flush with enough data to keep the maximum data in-flight.因此,循环直到 WSASend 挂起将使该连接与足够的数据保持一致,以保持最大数据在传输中。

Hope this makes sense.希望这是有道理的。

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".我看到这是一个性能帮助,但我 object 对所有文档说在 WSAGetOverlappedResult 中发送 TRUE 的 fWait 将等到 IO 请求“完成”。 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.好吧..我很惊讶我的理解是错误的......但是 TCP 处理得很好,以前没有给我造成问题。

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.我对如何使用暗示我的理解是正确的文字编写所有文档感到非常失望......当一直等待 IO 到“结束”、“完成”、“完成”时,绝对不会等待。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM