應swoole長鏈接開發調研相關TCP知識並記錄。php
如圖,若是我須要發送一條數據給用戶,實際的大小確定是大於你發送的大小,在各個數據層都進行了數據的封包,以便你的數據能完整的發給你想要的用戶。html
以太網的數據包的負載是1500字節,IP包頭須要20個字節,TCP的包頭須要20個字節,實際的數據內容大小則是1460個字節,如圖:react
應用層:nginx
如nginx、swoole等,大部分的數據都只須要關心應用層便可,我須要傳輸什麼數據,我只須要調用對應的方法、發送給已知的IP、端口便可。git
TCP層:算法
對應用層的數據進行包裝,TCP的報文格式以下圖,TCP/UDP層規定了數據的交換格式,如何進行握手、連接,若是加快數據傳輸、保證數據的完整性等。緩存
TCP層主要有幾個算法能夠關注下:swoole
慢啓動、擁塞避免、快速重傳、快恢復、滑動窗口網絡
IP層:tcp
細心的人也許已經發現TCP報文格式只有你發送的源端口和目標端口,並無要發送的IP地址和你的IP地址,這些其實都封包在IP層
數據鏈路層:
數據轉換爲frame(幀)進行數據傳輸,爲終端通訊提供傳輸媒體和連接,經常使用設備有網卡、交換機等
物理層:
傳輸比特流,物理設備傳輸的層,屬於硬件領域範疇,如光纖設備
Wireshark抓的某個包截圖:
1、端口號:用來標識同一臺計算機的不一樣的應用進程。
1)源端口:源端口和IP地址的做用是標識報文的返回地址。
2)目的端口:端口指明接收方計算機上的應用程序接口。
TCP報頭中的源端口號和目的端口號同IP數據報中的源IP與目的IP惟一肯定一條TCP鏈接。
2、序號和確認號:是TCP可靠傳輸的關鍵部分。序號是本報文段發送的數據組的第一個字節的序號。在TCP傳送的流中,每個字節一個序號。e.g.一個報文段的序號爲300,此報文段數據部分共有100字節,則下一個報文段的序號爲400。因此序號確保了TCP傳輸的有序性。確認號,即ACK,指明下一個期待收到的字節序號,代表該序號以前的全部數據已經正確無誤的收到。確認號只有當ACK標誌爲1時纔有效。好比創建鏈接時,SYN報文的ACK標誌位爲0。
3、數據偏移/首部長度:4bits。因爲首部可能含有可選項內容,所以TCP報頭的長度是不肯定的,報頭不包含任何任選字段則長度爲20字節,4位首部長度字段所能表示的最大值爲1111,轉化爲10進製爲15,15*32/8 = 60,故報頭最大長度爲60字節。首部長度也叫數據偏移,是由於首部長度實際上指示了數據區在報文段中的起始偏移值。
4、保留:爲未來定義新的用途保留,如今通常置0。
5、控制位:URG ACK PSH RST SYN FIN,共6個,每個標誌位表示一個控制功能。
1)URG:緊急指針標誌,爲1時表示緊急指針有效,爲0則忽略緊急指針。
2)ACK:確認序號標誌,爲1時表示確認號有效,爲0表示報文中不含確認信息,忽略確認號字段。
3)PSH:push標誌,爲1表示是帶有push標誌的數據,指示接收方在接收到該報文段之後,應儘快將這個報文段交給應用程序,而不是在緩衝區排隊。
4)RST:重置鏈接標誌,用於重置因爲主機崩潰或其餘緣由而出現錯誤的鏈接。或者用於拒絕非法的報文段和拒絕鏈接請求。
5)SYN:同步序號,用於創建鏈接過程,在鏈接請求中,SYN=1和ACK=0表示該數據段沒有使用捎帶的確認域,而鏈接應答捎帶一個確認,即SYN=1和ACK=1。
6)FIN:finish標誌,用於釋放鏈接,爲1時表示發送方已經沒有數據發送了,即關閉本方數據流。
6、窗口:滑動窗口大小,用來告知發送端接受端的緩存大小,以此控制發送端發送數據的速率,從而達到流量控制。窗口大小時一個16bit字段,於是窗口大小最大爲65535。
7、校驗和:奇偶校驗,此校驗和是對整個的 TCP 報文段,包括 TCP 頭部和 TCP 數據,以 16 位字進行計算所得。由發送端計算和存儲,並由接收端進行驗證。
8、緊急指針:只有當 URG 標誌置 1 時緊急指針纔有效。緊急指針是一個正的偏移量,和順序號字段中的值相加表示緊急數據最後一個字節的序號。 TCP 的緊急方式是發送端向另外一端發送緊急數據的一種方式。
9、選項和填充:最多見的可選字段是最長報文大小,又稱爲MSS(Maximum Segment Size),每一個鏈接方一般都在通訊的第一個報文段(爲創建鏈接而設置SYN標誌爲1的那個段)中指明這個選項,它表示本端所能接受的最大報文段的長度。選項長度不必定是32位的整數倍,因此要加填充位,即在這個字段中加入額外的零,以保證TCP頭是32的整數倍。
10、數據部分: TCP 報文段中的數據部分是可選的。在一個鏈接創建和一個鏈接終止時,雙方交換的報文段僅有 TCP 首部。若是一方沒有數據要發送,也使用沒有任何數據的首部來確認收到的數據。在處理超時的許多狀況中,也會發送不帶任何數據的報文段。
IP報文是對TCP的數據進行了一次包裝,再發送給數據鏈路層,IP報文格式固定格式爲20個字節,如圖:
更多協議(IP TCP UDP)的報文格式參考:
http://blog.51cto.com/mmanong/1962353
當第一次進行SYN創建連接的時候,客戶端會與服務端進行溝通MSS的大小,通常爲1460 Byte,每當有一個報文字段被確認,cwnd就增長一個MSS大小,這樣隨着網絡時間RTT的呈指數級增加,可是也不會一直指數級別增長,會有一個最大值的限制
<?php $server = new swoole_server("::", 9503); $server->on('connect', function ($server, $fd){ echo "connection open: {$fd}\n"; }); $server->on('receive', function ($server, $fd, $reactor_id, $data) { $server->send($fd, "Swoole: {$data}"); $server->close($fd); }); $server->on('close', function ($server, $fd) { echo "connection close: {$fd}\n"; }); $server->start();
客戶端發送數據後進行抓包,如圖:
統計-流量圖-顯示過濾器的限制,選擇TCP Flows:
從結果能夠看到tcp從SYN、ACK、FIN的整個過程及每一個過程的耗時狀況。
一、 TCP一次數據包發送數據大小不能超過MMS設置,通常爲1460字節
二、 TCP慢啓動特性在初始傳輸數據的時候並非直接發送1460數據,而經過慢啓動算法指數遞增,算法自己不支持進行參數改動
《TCP協議簡介》 http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html
《TCP擁塞控制慢啓動窗口設置》 https://blog.csdn.net/lishanmin11/article/details/77186820
《C語言setsockopt函數》 http://c.biancheng.net/cpp/html/374.html
《wireshark使用幫助》 http://www.cnblogs.com/dragonir/p/6219541.html
《網絡基本功系列文章》 https://wizardforcel.gitbooks.io/network-basic/content/7.html