C++ Windows IOCP - HTTP POST 数据丢失
我编写了一个非常简单的 IOCP HTTP 服务器,适用于 GET 动词,但不适用于 POST。
我创建一个套接字和一个侦听线程,其中accept() 正在等待连接。 当客户端连接时,我调用 ioctlsocket() 来解锁套接字,然后将套接字与 IOCP 关联起来,最后调用 WSARecv() 来读取数据。
确实读取了一些数据,当发生这种情况时,IOCP 通过 GetQueuedCompletionStatus() 唤醒工作线程,然后我恢复请求数据。
当我从任何浏览器发布时,我只会收到请求标头。关于原因有什么建议吗?
I have written a very simple IOCP HTTP server that works for the GET verb, but not POST.
I create a socket and a listen thread in which accept() is waiting for a connection.
When a client connects I call ioctlsocket() to unblock the socket then I associate the socket with IOCP and finally call WSARecv() to read the data.
Some data is indeed read and when that has happened, IOCP wakes up a worker thread via GetQueuedCompletionStatus() and I recover the request data.
I only ever get the request header when I POST from any browser. Any suggestions as to why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
TCP 套接字上的所有读取都将返回 1 字节到发送总量之间的任何位置,具体取决于您提供的缓冲区的缓冲区大小。可能发生的情况是,Web 服务器将数据作为两个单独的写入发送,而这恰好由服务器的 TCP 堆栈作为两个单独的数据块进行传输。您的读取即将完成,因为数据已到达。读取不会等到程序员期望的所有数据都到达,甚至不会等到缓冲区已满。
网络问题可能会进一步造成混乱,因为路由器可能会造成数据碎片,并且丢失的数据可能会在重新发送时延迟数据。
在使用 TCP 时,您始终需要假设您的读取每次仅返回一个字节并进行相应的编码;这样事情就会一直顺利。
您应该只发出另一次读取,当数据到达时您将获得其余的数据。
您可能想看看我的免费 IOCP 服务器框架(它也支持客户端),可以在 此处;听起来你已经把事情做好了,但有时能够考虑不同的做事方式会有所帮助。
当我需要在处理之前积累数据时,我倾向于采取以下方法。发出读取并等待它完成,看看我有什么,如果我没有得到我需要的所有内容并且我的缓冲区仍然有空间,请调整我正在使用的
WSABUF
使其指向刚刚到达同一缓冲区的当前数据的末尾并发出另一次读取;然后我们在同一个缓冲区中累积,直到我有足够的数据来处理它,或者我需要添加另一个缓冲区以获得更多数据。All reads on a TCP socket will return anywhere between 1 byte and the total amount sent depending on the buffer size of the buffer that you supply. What's likely happening is that the web server is sending the data as two separate writes and this happens to be being transmitted by the server's TCP stack as two separate blocks of data. Your read is completing because data has arrived. The read doesn't wait until all the data that you the programmer is expecting has arrived or even until your buffer is full.
Network issues can further confuse matters as routers may fragment things and lost data may delay things whilst it's resent.
Always when working with TCP you need to assume that your reads will always return just a single byte at a time and code accordingly; that way things will always work.
You should just issue another read and you'll get the rest of the data when it has arrived.
You might like to take a look at my free IOCP server framework (it does clients too) which can be found here; it sounds like you already have things working but sometimes being able to look at a different way of doing things helps.
When I need to accumulate data before processing I tend to take the following approach. Issue a read and wait for it to complete, look at what I have and, if I haven't got all I need and my buffer still has space in it, adjust the
WSABUF
that I'm using so that it points to the end of the current data that just arrived in the same buffer and issue another read; we then accumulate in the same buffer until either I have enough data to process it or I need to add another buffer on to get some more.