2012-01-31 102 views
0

我正在使用Berkely SOCKET API在linux下編寫TCP服務器。現在,客戶端有一組規範,客戶端發送的每條消息都基於這些規範,即客戶端發送的消息對應於規範指定的許多結構之一。現在情況是,服務器不知道客戶端將在什麼時間發送哪條消息。一旦我們得到消息,我們可以弄清楚它是什麼,但不是在此之前。由客戶端發送的消息具有可變長度,所以我們不能提前知道我們將得到什麼消息。爲了解決這個我已經使用下面的方法:如何正確使用recv()sys調用

const char *buf[4096] = { 0 }; 
      if (recv (connected, buf, 4096, 0) == -1) 
      { 
       printf ("Error in recvng message\n"); 
       exit (-1); 
      } 

即我使用大小4096的缺省緩衝液(沒有來自客戶端的消息可以是大於該尺寸)。收到該緩衝區,然後再把我檢查的消息類型,並採取相應措施如下:

struct ofp_header *oph; 
oph=(struct ofp_header *)buf; 
switch (oph->type) 
{ 
case example_pkt: 
handle_example_pkt(); 
break; 
} 

這工作得很好,但我只是想確認是不是一個合適的方法還是有別的東西,可能是比這更好。所有幫助非常感謝。

謝謝。

回答

5

TCP是基於流的。這意味着如果你使用比你的消息大的緩衝區,你也可能會收到下一條消息的一部分。

這意味着您需要知道消息的大小並將所有附加數據合併到下一條消息中。有兩個明顯的方式來做到這一點:

  1. 修改協議來發送每封郵件的大小作爲消息的前幾個字節。首先讀取大小,然後只讀取那麼多字節。

  2. 既然您知道每條消息的大小,請記錄您讀取的字節數。處理緩衝區中的第一條消息,然後從緩衝區中剩餘的字節中減去該消息的大小。繼續重複此過程,直到您或者A.沒有足夠的字節來標識消息類型或B.沒有足夠的字節用於檢測到的類型的消息。保存剩餘的字節並再次調用recv以讀取更多數據。

+0

是的,這是我所害怕的。你可以請發佈解決方案嗎? – Abdullah 2012-01-31 14:37:08

+0

請參閱編輯答案。 – 2012-01-31 15:00:39

+0

非常感謝,非常感謝,現在很清楚該怎麼辦:)乾杯:) – Abdullah 2012-01-31 15:57:42