資料接收中粘包及半包的處理

2021-04-13 08:37:31 字數 1927 閱讀 3072

在使用tcp協議的網路應用中,不可避免需要處理的乙個問題就是半包和粘包的情況。

一種做法是在接收端設乙個比較大的緩衝區,先將收到的資料報都放到緩衝區中,然後從該緩衝區中選取完整的資料報出來。該緩衝區的實現可以使用環形緩衝區進行優化,避免頻繁的資料移動。使用該方法的乙個描述見 http://www.vckbase.com/document/viewdoc/?id=1203

另外一種做法就是在接收的時候就只接收完整包。這要求資料報有固定的包頭結構體,其中還要包含資料報的長度資訊。在服務端接收的時候,先接收該包頭資料,然後再接收指定長度的資料體。

在ace中,用於儲存訊息的ace_message_block有乙個重要的特性:復合。即將多條訊息連線在一起,形成乙個單鏈表。這樣便可以將先收到的包頭和後收到的包體連成乙個複合體,而不用建乙個大的資料報,將兩個message_block拷貝進去。

下面的示例採用ace的proactor框架完成,實現了伺服器端半包及粘包的處理,以及ace_message_block的復合,網路io與邏輯處理的分離。

在proactor框架中,接收新連線後,會初始化乙個讀請求,此時只要求讀包頭長度的資料:

void init_read_stream()

這裡由於使用了網路io與邏輯處理分執行緒處理的方式,遞交給邏輯執行緒的資料報前面還加上了標識網路連線的handle,用以告訴邏輯執行緒該資料報是哪個客戶端連線發上來的。

遞交給邏輯執行緒的資料報頭結構為:

struct packetheader

;其中data_length就是從接收到的資料報中獲取到的。

對於粘包的情況比較容易處理,先收了包頭後再接收指定長度的資料報,多餘的資料由下次再讀取。

半包情況稍微複雜一點,每個資料報是分兩次接收的,兩次接收的時候都有可能接收不完全。

當接收包頭不完全時所做的處理是繼續提交讀請求,讀的資料長度為剩餘的包頭長度

if (this->recv_data_->length() < sizeof(packetheader))

當包頭接收完後,新建乙個message_block,長度為需要接收的資料體長度,並將該message_block鏈結到包頭後

packetheader * hdr = reinterpret_cast(this->recv_data_->rd_ptr());

ace_message_block * data_mb = this->recv_data_->cont();

if (!data_mb)

如果該資料報的包體接收完全,則將該完整的資料報傳送到邏輯執行緒的訊息佇列,然後初始化乙個新的接收請求

if (data_mb->length () == hdr->data_length)

否則表示資料體還未接收完全,處理方法也是繼續提交剩餘資料的讀請求

this->reader_.read (*data_mb, data_mb->space ());

直接該資料報讀取完全。

資料報接收處理函式的完整實現為:

virtual void handle_read_stream (const ace_asynch_read_stream::result &result)

else

packetheader * hdr = reinterpret_cast(this->recv_data_->rd_ptr());

ace_message_block * data_mb = this->recv_data_->cont();

if (!data_mb)

if (data_mb->length () == hdr->data_length)

// 否則繼續接收該資料報

this->reader_.read (*data_mb, data_mb->space ());}}

完整的伺服器實現和模擬半包及粘包情況的客戶端**見

資料接收中粘包及半包的處理

在使用tcp協議的網路應用中,不可避免需要處理的乙個問題就是半包和粘包的情況。一種做法是在接收端設乙個比較大的緩衝區,先將收到的資料報都放到緩衝區中,然後從該緩衝區中選取完整的資料報出來。該緩衝區的實現可以使用環形緩衝區進行優化,避免頻繁的資料移動。使用該方法的乙個描述見 另外一種做法就是在接收的時...

資料接收中粘包及半包的處理

在使用tcp協議的網路應用中,不可避免需要處理的乙個問題就是半包和粘包的情況。一種做法是在接收端設乙個比較大的緩衝區,先將收到的資料報都放到緩衝區中,然後從該緩衝區中選取完整的資料報出來。該緩衝區的實現可以使用環形緩衝區進行優化,避免頻繁的資料移動。使用該方法的乙個描述見 另外一種做法就是在接收的時...

半包粘包處理

資料接收中粘包及半包的處理 資料接收中粘包及半包的處理 2006 10 16 09 45 在使用tcp協議的網路應用中,不可避免需要處理的乙個問題就是半包和粘包的情況。一種做法是在接收端設乙個比較大的緩衝區,先將收到的資料報都放到緩衝區中,然後從該緩衝區中選取完整的資料報出來。該緩衝區的實現可以使用...