天天看點

《Linux高性能伺服器程式設計》——3.7 TCP成塊資料流

下面考慮用ftp協定傳輸一個大檔案。在ernest-laptop上啟動一個vsftpd伺服器程式(更新的、安全版的ftp伺服器程式),并執行ftp指令登入該伺服器上,然後在ftp指令提示符後輸入get指令,從伺服器下載下傳一個幾百兆的大檔案。同時用tcpdump抓取這一個過程中ftp用戶端和vsftpd伺服器交換的tcp封包段。具體操作過程如下:

代碼清單3-5是該過程的部分tcpdump輸出。

《Linux高性能伺服器程式設計》——3.7 TCP成塊資料流
《Linux高性能伺服器程式設計》——3.7 TCP成塊資料流

注意,用戶端發送的最後兩個tcp封包段17和18,它們分别是對tcp封包段2和16的确認(從序号值和确認值來判斷)。由此可見,當傳輸大量大塊資料的時候,發送方會連續發送多個tcp封包段,接收方可以一次确認所有這些封包段。那麼發送方在收到上一次确認後,能連續發送多少個tcp封包段呢?這是由接收通告視窗(還需要考慮擁塞視窗,見後文)的大小決定的。tcp封包段17說明用戶端還能接收30?084×64位元組(本例中視窗擴大因子為6),即1?925?376位元組的資料。而在tcp封包段18中,接收通告視窗大小為1?748?288位元組,即用戶端能接收的資料量變小了。這表明用戶端的tcp接收緩沖區有更多的資料未被應用程式讀取而停留在其中,這些資料都來自tcp封包段3~16中的一部分。伺服器收到tcp封包段18後,它至少(因為接收通告視窗可能擴大)還能連續發送的未被确認的封包段數量是1?748?288/16?384個,即106個(但一般不會連續發送這麼多)。其中,16?384是成塊資料的長度(見tcp封包段1~16的length值),很顯然它小于但接近mss規定的16?396位元組。

另外一個值得注意的地方是,伺服器每發送4個tcp封包段就傳送一個psh标志(tcpdump輸出标志p)給用戶端,以通知用戶端的應用程式盡快讀取資料。不過這對伺服器來說顯然不是必需的,因為它知道用戶端的tcp接收緩沖區中還有空閑空間(接收通告視窗大小不為0)。

下面我們修改系統的tcp接收緩沖區和tcp發送緩沖區的大小(如何修改将在第16章介紹),使之都為4096位元組,然後重新開機vsftpd伺服器,并再次執行上述操作。此次tcpdump的部分輸出如代碼清單3-6所示。

《Linux高性能伺服器程式設計》——3.7 TCP成塊資料流
《Linux高性能伺服器程式設計》——3.7 TCP成塊資料流

從同步封包段(未在代碼清單3-6中列出)得知在這次通信過程中,用戶端和伺服器的視窗擴大因子都為0,因而用戶端和伺服器每次通告的視窗大小都是3072位元組(沒超過4096位元組,預料之中)。因為每個成塊資料的長度為1536位元組,是以伺服器在收到上一個tcp封包段的确認之前最多還能再發送1個tcp封包段,這正是tcp封包段1~3描述的情形。

繼續閱讀