C++ asio read-从套接字读取所有数据后返回,无需等待EOF

C++ asio read-从套接字读取所有数据后返回,无需等待EOF,c++,http,boost,boost-asio,C++,Http,Boost,Boost Asio,我是boost的新手::asio,我遇到了一个我真的不知道如何解决的问题,你能帮助我吗 一般来说,我试图实现基于boost::asio的代理。我使用async_read_some函数从服务器读取响应,类似于: _ssocket.async_read_some(boost::asio::buffer(_sbuffer), boost::bind(&connection::handle_server_read_body_some,

我是boost的新手::asio,我遇到了一个我真的不知道如何解决的问题,你能帮助我吗

一般来说,我试图实现基于boost::asio的代理。我使用async_read_some函数从服务器读取响应,类似于:

        _ssocket.async_read_some(boost::asio::buffer(_sbuffer),
                boost::bind(&connection::handle_server_read_body_some,
                        shared_from_this(),
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred
            ));
一切正常,它读取一些数据和调用处理程序。问题是在我校准async_read_某个函数的时候,并且没有更多的数据可以从套接字读取。因此,大约15秒钟内不会调用处理程序,直到EOF被清除为止。(因此服务器套接字已断开连接)。我尝试过不同的读取函数,它们都只在读取或出现错误时返回1个或多个字节

问题是,有时我不知道需要读取多少字节,所以我只需要读取当前的所有内容。我试着用

boost::asio::socket_base::bytes_readable

为了弄清楚套接字上有多少字节可用,但问题是这些函数返回的字节数可以在不阻塞的情况下读取,所以我不能将我的实现建立在这个基础上,即使从测试中,我看到有时候字节可读返回0——下一次调用同一套接字上的异步读取——读取一堆数据

我的问题是-当套接字中没有更多的数据可读取时,是否有任何方法可以获得imidiate返回(在同步调用的情况下)/处理程序调用(在异步的情况下)?因为目前它只是挂起15秒直到EOF


我将感谢您给我的任何建议或提示。

您使用Boost.Asio没有任何问题。问题是您需要知道如何处理HTTP消息。基本上,您需要检测消息类型并对其进行解析以了解其长度。服务器断开连接并不总是如此,因为HTTP支持保持活动(同一连接用于多条消息)。请阅读RFC 2616的以下报价:

4.4信息长度

消息的传输长度是消息正文的长度,如下所示: 它出现在消息中;也就是说,在任何转移编码完成后 已应用。当消息正文包含在消息中时 该主体的转移长度由以下其中一项决定(in 优先顺序):

1.任何“不得”包含消息正文的响应消息(例如1xx、204和304响应以及对HEAD请求的任何响应) 始终由标题字段后的第一个空行终止, 不考虑消息中存在的实体标头字段

2.如果存在传输编码头字段(第14.41节),且该字段具有除“标识”以外的任何值,则传输长度为 通过使用“分块”传输编码(第3.6节)定义,除非 通过关闭连接终止消息

3.如果存在内容长度标题字段(第14.13节),则其十进制值(以八位字节为单位)表示实体长度和长度 传输长度。如果出现以下情况,则不得发送内容长度标题字段: 这两个长度不同(即,如果传输编码

 header field is present). If a message is received with both a
 Transfer-Encoding header field and a Content-Length header field,
 the latter MUST be ignored.
4.如果消息使用媒体类型“multipart/byteranges”,并且没有另外指定传输长度,那么这种自定界 媒体类型定义传输长度。此媒体类型不能为 除非发送方知道接收方可以解析它,否则使用 存在于具有多字节范围的范围标头请求中 来自1.1客户端的说明符意味着客户端可以解析 多部分/byteranges响应

   A range header might be forwarded by a 1.0 proxy that does not
   understand multipart/byteranges; in this case the server MUST
   delimit the message using methods defined in items 1,3 or 5 of
   this section.
5.由服务器关闭连接。(关闭连接不能用于指示请求正文的结束,因为这样会离开 服务器不可能发回响应。)

为了与HTTP/1.0应用程序兼容,HTTP/1.1请求 包含消息正文的邮件必须包含有效的内容长度标头 字段,除非已知服务器符合HTTP/1.1。如果 请求包含消息正文,但未给出内容长度 如果无法确定,服务器应响应400(错误请求) 消息的长度,如果需要,可使用411(所需长度) 坚持接收有效的内容长度

所有接收实体的HTTP/1.1应用程序都必须接受 “分块”传输编码(第3.6节),从而允许这种机制 在无法确定消息长度时用于消息 提前

消息不能同时包含内容长度标头字段和 非身份传输编码。如果消息包含非- 身份传输编码,必须忽略内容长度

当在消息中给定内容长度时,消息体为 允许,其字段值必须与中的八位字节数完全匹配 消息正文.HTTP/1.1用户代理必须在 接收并检测到无效长度


我认为您在这里遇到了TCP/IP的基本原理。套接字如何知道除了远程套接字告诉它(即EOF)之外,什么时候没有更多的数据可读取?使用流式套接字(如TCP)不可能知道,因为它是流式传输。像TCP连接这样的网络流很像现实生活中的流,数据从一端流向另一端,没有尽头,而结束流的唯一方法是切断连接。如果您想要消息边界,请将它们添加到协议中(或使用包含消息边界的协议),或者使用UDP.Hm…但是你认为需要10-15秒来告诉我吗?我的意思是,是的,我同意你的观点,并且希望远程套接字在没有更多数据的情况下发出通知,但是这个延迟有点太长了,你不这样认为吗?@JoachimPileborg谢谢,因为删除端在10-15秒之后才关闭它的连接?这取决于在协议上,你甚至有责任发回一些东西或关闭监狱
   A range header might be forwarded by a 1.0 proxy that does not
   understand multipart/byteranges; in this case the server MUST
   delimit the message using methods defined in items 1,3 or 5 of
   this section.