2013-05-16 50 views
1

我很新的boost :: asio,我遇到了一个问题,我真的不知道如何解决,请问您可以请帮我。boost :: asio read - 返回所有数据从套接字读取,而不等待EOF

一般来说,我试图实现基于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) 

要figgure了多少字节的插座avaliable,但问题是,这些函数会返回一个可以无阻塞地读取的字节数,这样我就可以不要以我的实现为基础,即使是从测试中看到,有时,bytes_readable返回0,然后在同一个套接字上调用async_read_some,读取大量数据。

我的问题是有没有什么办法来获得亚胺化返回(在同步调用的情况下)/处理程序调用(在异步的情况下),当没有更多的数据从套接字读取?因为目前它只持续15秒直到EOF。

我会appriciate任何意见或提示,你可以给我。

+2

我认为你面对的TCP/IP,这里的基本面。除了远程套接字告诉它(即EOF)时,套接字如何知道什么时候没有更多的数据要读取? – Nick

+2

使用流式套接字(如TCP)不可能知道,因为它是流式传输。像TCP连接这样的网络流就像现实生活中的一个流,数据从一端流向另一端,而结束流的唯一方法是切断连接。如果你想要消息边界,那么要么将它们添加到你的协议中(要么使用包含消息边界的协议),要么使用UDP。 –

+0

嗯......但你认为需要10-15秒才能说出来吗?我的意思是,是的,我同意你的观点,并期望远程套接字在没有更多数据存在的情况下可以通知,但是这个延迟有点太长,你不这么认为吗? – miks131

回答

3

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

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

4.4长度限制

消息的转发长度是所述消息体的长度为 它出现在消息中;也就是说,在任何传输编码已经应用 之后。当消息包含消息体时,该身体的传输长度由以下之一决定( 优先顺序):

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

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

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

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.如果消息使用的媒体类型“多部分/字节范围”,并转让-length不另外指明,则此自界定 媒体类型定义了传送长度不得 使用该媒体类型,除非发送者知道接收者可以解析它;所述 存在下,在Range头部的请求具有多个字节级范围从1.1客户端 符意味着客户机可以解析 的multipart /字节范围响应。

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.By服务器关闭连接。 (关闭连接不能用于指示请求主体的结束,因为这将使 不可能由服务器发送回应。)

为了与HTTP/1.0应用程序兼容,HTTP/1.1请求 包含一个消息主体必须包含一个有效的Content-Length头域 字段,除非已知服务器符合HTTP/1.1。如果 请求包含一个消息主体和一个内容长度没有给出,所述 服务器应该与400(坏请求)响应,如果它不能确定 消息的长度,或与411(需要的长度)如果它希望 坚持接收有效的内容长度。接收实体必须接受

所有HTTP/1.1的应用“分块”传输编码(第3.6节),从而允许用于消息这个机制 当消息长度不能预先确定 。

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

如果在邮件中给出了Content-Length,其邮件正文允许为 ,则其字段值务必与邮件正文中的OCTET数量完全匹配。当接收和检测到无效长度时,HTTP/1.1用户代理务必通知用户。

+0

如果Https连接正在通过代理进行,那么首次连接将在客户端和服务器之间建立连接。然后所有数据都将以加密格式进行传输。在这种情况下,如何读取内容。因为连接将保持活动状态,直到整个数据为止交换。 – asim

+0

@ user1276728:HTTPS:[从技术上讲,它本身不是协议;相反,它是简单地将超文本传输​​协议(HTTP)分层在SSL/TLS协议之上](http://en.wikipedia.org/wiki/HTTP_Secure)的结果。因此,这里没有任何区别,您从SSL套接字获得的数据已经被解密,您可以将其视为HTTP数据包。 –

+1

上面我提到通过代理我正在阅读内容。所以在HTTPS的情况下,代理将充当客户端和服务器之间的隧道。因此,无论我从客户端获得的加密内容,我都必须传输到服务器。我的问题是如何在不知道任何标题的情况下阅读加密内容。 – asim

相关问题