2013-05-16 51 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

相關問題