1

我对 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_some 函数的那一刻 - 没有更多数据可以从套接字读取。所以处理程序不会在大约 15 秒内被调用 - 直到 EOF 被触发。(因此服务器套接字断开连接)。我尝试了不同的读取函数,并且所有这些函数仅在读取 1 个或 mote 字节或出现错误时返回。

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

boost::asio::socket_base::bytes_readable

或者

 _ssocket.available(err)

要弄清楚套接字上有多少字节可用,但问题是这些函数返回的字节数可以在没有阻塞的情况下读取,所以我不能以此为基础实现我的实现,即使从测试中我看到有时 bytes_readable 会返回 0 -并在同一个套接字上调用 async_read_some - 读取一堆数据。

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

我会向您提供任何建议或提示。

4

1 回答 1

3

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

http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html

4.4 消息长度

消息的传输长度是消息中出现的消息体的长度;也就是说,在应用了任何传输编码之后。当消息中包含消息正文时,该正文的传输长度由以下之一确定(按优先顺序):

1.任何“MUST NOT”包含消息体的响应消息(例如 1xx、204 和 304 响应以及对 HEAD 请求的任何响应)总是由头字段之后的第一个空行终止,无论消息中存在的实体头字段。

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

3. 如果存在 Content-Length 头字段(第 14.13 节),则其在 OCTET 中的十进制值表示实体长度和传输长度。如果这两个长度不同(即,如果传输编码

 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 客户端的具有多个字节范围说明符的 Range 标头的存在意味着客户端可以解析 multipart/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 请求必须包含有效的 Content-Length 头字段,除非已知服务器符合 HTTP/1.1。如果请求包含消息正文并且没有给出 Content-Length,如果服务器无法确定消息的长度,则应该返回 400(错误请求),如果它希望坚持使用 411(需要长度)接收有效的内容长度。

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

消息不得同时包含 Content-Length 头字段和非身份传输编码。如果消息确实包含非身份传输编码,则必须忽略 Content-Length。

当在允许消息体的消息中给出 Content-Length 时,其字段值必须与消息体中的八位字节数完全匹配。HTTP/1.1 用户代理必须在收到和检测到无效长度时通知用户。

于 2013-05-16T13:33:22.313 回答