1. 程式人生 > >TCP網路程式設計處理的三個半事件

TCP網路程式設計處理的三個半事件

TCP網路程式設計最本質的是處理三個半事件:

  1. 連線建立:包括伺服器端被動接受連線(accept)和客戶端主動發起連線(connect)。TCP連線一旦建立,客戶端和服務端就是平等的,可以各自收發資料。
  2. 連線斷開:包括主動斷開(closeshutdown)和被動斷開(read()返回0)。
  3. 訊息到達:檔案描述符可讀。這是最為重要的一個事件,對它的處理方式決定了網路程式設計的風格(阻塞還是非阻塞,如何處理分包,應用層的緩衝如何設計等等)。
  4. 訊息傳送完畢:這算半個。對於低流量的服務,可不必關心這個事件;另外,這裡的“傳送完畢”是指資料寫入作業系統緩衝區(核心緩衝區),將由TCP協議棧負責資料的傳送與重傳,不代表對方已經接收到資料。

下面我們重點討論一下訊息到達訊息傳送完畢事件:

訊息到達事件 

socket有資料到來時,資料先被核心接收,存放在核心接收緩衝區中,網路庫事件迴圈中的可讀事件被觸發,將資料從核心緩衝區移動到應用緩衝區中,並且網路庫會回撥一個OnMessage函式表示有訊息到達。

由於TCP接收到的可能是半包(即資料不完整),OnMessage要根據協議來判斷這個資料包是否完整。

而如果TCP接收到的資料包是完整的,就直接將這個資料包取出來進行處理(read->decode->compute->encode->write);而如果TCP接收到的資料包不完整,則OnMessage立即返回,這樣核心再接收到一些資料時,網路庫事件迴圈中的可讀事件又會被觸發...直到OnMessage發現數據包已經完整了,才它取出來進行處理(read->decode->compute->encode->write)。

訊息傳送完畢事件

假設現在應用層要傳送資料,如果核心傳送緩衝區足夠大,則將要傳送的資料全部填入核心緩衝區中,並觸發一個傳送完成事件,並且網路庫會回撥一個OnWriteComplete函式表示訊息傳送完畢;而如果核心傳送緩衝區不足以容納這麼多的資料,則只將其中一部分資料填入核心緩衝區,剩餘部分追加到應用層的傳送緩衝區中,等核心傳送緩衝區將資料傳送出去後,會觸發一個可寫事件,在這個事件中就會將應用層傳送緩衝區中的資料填充到核心傳送緩衝區中,這時如果核心傳送緩衝區不足以容納應用層傳送緩衝區中的全部資料,則只將其中一部分資料填入核心緩衝區...就這樣直到應用層傳送緩衝區中的資料全部填充到核心緩衝區,網路庫事件迴圈中的傳送完成事件會被觸發,並回調OnWriteComplete表示訊息傳送完畢。

注意:應用層一定要在應用層傳送緩衝區中的資料全部填入核心緩衝區並回調OnWriteComplete表示訊息傳送完畢後才能繼續傳送資料,這樣做可以避免資料丟包。