簡體   English   中英

關於recv和讀緩沖區 - C Berkeley套接字

[英]About recv and the read buffer - C Berkeley Sockets

我正在使用berkeley套接字和TCP(SOCK_STREAM套接字)。

過程是:

  1. 我連接到遠程地址。
  2. 我發了一條消息給它。
  3. 我收到了一條消息。

想象一下,我使用以下緩沖區:

char recv_buffer[3000];
recv(socket, recv_buffer, 3000, 0);

問題是:

  • 如何在第一次調用recv后讀取緩沖區是否為空? 如果它不是空的,我將不得不再次調用recv,但是如果我在空的時候這樣做,我會讓它阻塞很長時間。
  • 我怎么知道我已經將多少字節重新加入recv_buffer? 我不能使用strlen,因為我收到的消息可以包含空字節。

謝謝。

如何在第一次調用recv后讀取緩沖區是否為空? 如果它不是空的,我將不得不再次調用recv,但是如果我在空的時候這樣做,我會讓它阻塞很長時間。

您可以使用selectpoll系統調用以及套接字描述符來判斷是否有數據等待從套接字讀取。

但是,通常應該有一個由發送方和接收方都遵循的商定協議,以便雙方知道要傳輸多少數據。 例如,發送方可能首先發送一個2字節的整數,表示它將發送的字節數。 接收器然后首先讀取這個2字節的整數,以便它知道從套接字讀取多少字節。

無論如何,正如Tony在下面指出的那樣,一個健壯的應用程序應該在頭文件中使用長度信息的組合,並在每次調用recv之前輪詢套接字以獲取其他數據(或者使用非阻塞套接字)。 這將阻止您的應用程序阻止,例如,您知道(從標題)仍然有100個字節要讀取,但對等方無法出於任何原因發送數據(也許對等計算機是意外關閉),從而導致你的recv調用阻止。

我怎么知道我已經將多少字節重新加入recv_buffer? 我不能使用strlen,因為我收到的消息可以包含空字節。

recv系統調用將返回讀取的字節數,如果發生錯誤,則返回-1。

從recv(2)的手冊頁:

[recv]返回接收的字節數,如果發生錯誤則返回-1。 當對等體執行有序關閉時,返回值將為0。

如何在第一次調用recv后讀取緩沖區是否為空?

即使是第一次(在接受客戶端之后),如果客戶端連接丟失,recv也會阻塞並失敗。 你必須:

  • 使用selectpoll (BSD套接字)或某些特定於操作系統的等效項,可以告訴您特定套接字描述符上是否有可用的數據(以及異常條件,以及可以寫入更多輸出的緩沖區空間)
  • 你可以將套接字設置為非阻塞,這樣recv只會返回任何可立即獲得的東西(可能沒有)
  • 你可以創建一個線程,你能負擔得起有塊recv -ing數據,知道其他線程會做你擔心繼續與其他工作

我怎么知道我已經將多少字節重新加入recv_buffer? 我不能使用strlen,因為我收到的消息可以包含空字節。

recv()返回讀取的字節數,或者出錯時返回-1。

請注意,TCP是字節流協議,這意味着您只能保證能夠以正確的順序從中讀取和寫入字節,但不保證保留消息邊界。 因此,即使發送方對其套接字進行了大量單個寫入,它也可以在路由中分段並到達幾個較小的塊,或者可以通過一個recv()合並和檢索幾個較小的send() / write() 。 / read()

因此,請確保循環調用recv直到獲得所需的所有數據(即可以處理的完整邏輯消息)或錯誤。 您應該准備好/能夠處理從您的客戶端獲取部分/全部后續send (如果您沒有協議,每個方只在從另一方獲取完整消息后發送,並且不使用具有消息長度的標頭)。 請注意,對消息頭執行recvs(帶有長度),然后正文可能會導致對recv()更多調用,從而對性能產生潛在的負面影響。

這些可靠性問題經常被忽略。 當它們在單個主機上時,它們表現得更少,可靠且快速的LAN,涉及的路由器和交換機更少,以及更少或非並發消息。 然后他們可能會在負載和更復雜的網絡上崩潰。

  1. 如果recv()返回少於3000個字節,則可以假定讀取緩沖區為空。 如果它在3000字節緩沖區中返回3000個字節,那么您最好知道是否繼續。 大多數協議包括TLV的一些變化 - 類型,長度,值。 每條消息都包含一條消息類型的指示符,一些長度(如果長度固定,可能由類型暗示)和值。 如果在讀取您收到的數據時,您發現最后一個單元不完整,您可以假設還有更多要讀取的單元。 您還可以將套接字轉換為非阻塞套接字; 如果沒有讀取數據,則recv()將失敗並顯示EAGAIN或EWOULDBLOCK。

  2. recv()函數返回讀取的字節數。

帶有FIONREAD選項的ioctl()告訴您當前可以無阻塞地讀取多少數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM