<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## TCP協議的特點 1. 使用TCP協議協議通信的雙方必須先建立連接,然后才能開始數據的讀寫。 2. TCP協議連接是一對一的,基于廣播和多播的應用程序不能使用TCP服務。無連接的UPD適合于廣播和多播。 3. 當發送端應用程序連續執行多次寫操作時,TCP模塊先將這些數據放入TCP發送緩沖區中,當TCP模塊真正開始發送數據時,發送緩沖區中這些等待發送的數據可能被封裝成一個或多個TCP報文。因此TCP模塊發出的TCP報文段的個數和應用程序執行的寫操作次數之間沒有固定的數量關系。 4. 當接收端收到一個或多個TCP報文后,TCP模塊將他們攜帶的應用程序數據按照TCP報文段的序號依次放入TCP接收緩沖區中,并通知應用程序讀取數據。因此應用程序執行的讀操作次數和TCP模塊接收的TCP報文段的個數之間沒有固定的數量關系。 5. UDP協議在發送端應用程序每執行一次寫操作,UDP模塊就將其封裝成一個UDP數據發送之,接收端必須及時針對每一個UDP數據報執行讀操作,否則就丟包。 ![](https://files.catbox.moe/aanrvl.png) >應用程序執行的寫操作次數和接收端執行的讀操作次數沒有任何數量關系,這就是字節流的概念 ## TCP固定頭部結構 TCP頭部信息出現在每個TCP報文中。 ![](https://files.catbox.moe/pms3l0.png) 16位端口號:來自哪里,以及傳給哪個上層協議或應用程序。 32位序號:一次TCP通信過程中某一個傳輸方向上的字節流的每個字節編號。序號之被初始化為某個隨機值ISN。后續TCP報文段中序號值被系統設置為ISN+該報文段所攜帶數據的第一個字節在整個字節流中的偏移。 32位確認號:用作另一方發送來的TCP報文段的響應。其值是收到的TCP報文段的序號值加1。 4位頭部長度:標識該TCP頭部有多少32位(4字節),因為4位最大能表示15,所以TCP頭部最長是60字節。 6位標志包含如下選項: * URG標志,表示緊急指針是否有效 * ACK標志,表示確認號是否有效。攜帶ACK標志的TCP報文段為確認報文段。 * PSH標志:提示接收端應立即從TCP接收緩沖區讀走數據,為接收后續數據騰出空間。 * RST標志,表示要求對方重新建立連接。我們稱攜帶RST標志的TCP報文段為復位報文段 * SYN標志,表示請求建立一個連接,我們稱攜帶SYN標志的TCP報文段為同步報文段。 * FIN標志,表示通知對方本端要關閉連接了。攜帶FIN標志的報文段為結束報文段。 16位窗口大小:是TCP流量控制的一個手段,這里說的窗口,指的是接收通告窗口,它告訴對方本端的TCP接收緩沖區還能容納多少字節的數據,這樣就可以控制發送數據的速度 16位校驗和:由發送端填充,接收端對TCP報文段執行CRC算法以檢驗TCP報文段在傳輸過程中是否損壞。注意,這個校驗不僅包括TCP頭部,也包括數據部分,這也是TCP可靠傳輸的一個重要保障。 16位緊急指針:是一個正的偏移量。它和序號字段的值相加表示最后一個緊急數據的下一字節的序號。因此,確切的說,這個字段是緊急指針相對當前序號的偏移,不妨稱之為緊急偏移。TCP的緊急指針是發送端向接收端發送緊急數據的方法。 ## TCP頭部選項 TCP頭部的最后一個選項字段,是可變長的可選信息,這部分最多包含40字節,因為TCP頭部最長是60字節。 ![](https://files.catbox.moe/8zs7y8.png) ## TCP的連接和斷開 ### 準備 server ``` $ nc -l 8881 ``` client: ``` nc 127.0.0.1 8881 ``` ### tcpdump ``` sudo tcpdumo port 8881 -S ``` > -S 的作用是為了顯示絕對值,否則第三次握手的時候tcpdumo會簡化輸出,ack的值是1. tcpdump參數 ``` 使用tcpdump抓包查看tcp三次握手過程 參數說明: -c????????指定包個數 -n??????? IP、端口用數字方式顯示 -i ? ? ? ? 指定網卡,默認為eth0 -X ? ? ? 把協議頭和包內容以16進制和ASCII的形式顯示出來,對進行協議分析時很有用 -e ? ? ? 輸出增加以太網幀頭部信息 -F ? ? ? 指定過濾表達式所在的文件 -w ? ? ?將流量保存到文件中,二進制格式 -r ? ? ? 讀取參數-w保存的文件 port ? 指定端口 ``` ### 連接 建立TCP連接需要三次握手 ``` 12:16:12.918224 IP 115.231.93.68.37210 > VM-0-7-ubuntu.8881: Flags [S], seq 3339588145, win 64240, options [mss 1424,sackOK,TS val 2782499184 ecr 0,nop,wscale 7], length 0 12:16:12.918294 IP VM-0-7-ubuntu.8881 > 115.231.93.68.37210: Flags [S.], seq 1394745198, ack 3339588146, win 65160, options [mss 1460,sackOK,TS val 897553608 ecr 2782499184,nop,wscale 7], length 0 12:16:12.933025 IP 115.231.93.68.37210 > VM-0-7-ubuntu.8881: Flags [.], ack 1394745199, win 502, options [nop,nop,TS val 2782499199 ecr 897553608], length 0 ``` x = 3339588145 y = 1394745198 * 第一次握手(SYN=1, seq=x): 客戶端發送一個 TCP 的 SYN 標志位置1的包,指明客戶端打算連接的服務器的端口,以及初始序號 X,保存在包頭的序列號(Sequence Number)字段里。 發送完畢后,客戶端進入`SYN_SEND`狀態。 * 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1): 服務器發回確認包(ACK)應答。即 SYN 標志位和 ACK 標志位均為1。服務器端選擇自己 ISN 序列號,放到 Seq 域里,同時將確認序號(Acknowledgement Number)設置為客戶的 ISN 加1,即X+1。 發送完畢后,服務器端進入`SYN_RCVD`狀態。 * 第三次握手(ACK=1,ACKnum=y+1) 客戶端再次發送確認包(ACK),SYN 標志位為0,ACK 標志位為1,并且把服務器發來 ACK 的序號字段+1,放在確定字段中發送給對方,并且在數據段放寫ISN的+1 發送完畢后,客戶端進入`ESTABLISHED`狀態,當服務器端接收到這個包時,也進入`ESTABLISHED`狀態,TCP 握手結束。 ### 連接斷開 TCP連接的斷開需要四次揮手。 ``` 12:17:01.598449 IP 115.231.93.68.37210 > VM-0-7-ubuntu.8881: Flags [F.], seq 3339588146, ack 1394745199, win 502, options [nop,nop,TS val 2782547865 ecr 897553608], length 0 12:17:01.598546 IP VM-0-7-ubuntu.8881 > 115.231.93.68.37210: Flags [F.], seq 1394745199, ack 3339588147, win 510, options [nop,nop,TS val 897602288 ecr 2782547865], length 0 12:17:01.612711 IP 115.231.93.68.37210 > VM-0-7-ubuntu.8881: Flags [.], ack 1394745200, win 502, options [nop,nop,TS val 2782547879 ecr 897602288], length 0 ``` x = 3339588146 y= 1394745199 * **第一次揮手**(FIN=1,seq=x) 假設客戶端想要關閉連接,客戶端發送一個 FIN 標志位置為1的包,表示自己已經沒有數據可以發送了,但是仍然可以接受數據。 發送完畢后,客戶端進入`FIN_WAIT_1`狀態。 * **第二次揮手**(ACK=1,ACKnum=x+1) 服務器端確認客戶端的 FIN 包,發送一個確認包,表明自己接受到了客戶端關閉連接的請求,但還沒有準備好關閉連接。 發送完畢后,服務器端進入`CLOSE_WAIT`狀態,客戶端接收到這個確認包之后,進入`FIN_WAIT_2`狀態,等待服務器端關閉連接。 * **第三次揮手**(FIN=1,seq=y) 服務器端準備好關閉連接時,向客戶端發送結束連接請求,FIN 置為1。 發送完畢后,服務器端進入`LAST_ACK`狀態,等待來自客戶端的最后一個ACK。 * **第四次揮手**(ACK=1,ACKnum=y+1) 客戶端接收到來自服務器端的關閉請求,發送一個確認包,并進入`TIME_WAIT`狀態,等待可能出現的要求重傳的 ACK 包。 服務器端接收到這個確認包之后,關閉連接,進入`CLOSED`狀態。 客戶端等待了某個固定時間(兩個最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒有收到服務器端的 ACK ,認為服務器端已經正常關閉連接,于是自己也關閉連接,進入`CLOSED`狀態。 可以看到實際tcpdump打印出來的數據是,第二次揮手和第三次揮手整合成了一個包返回給客戶端。 這是因為關閉連接有兩種方式,當一方關閉連接,另外一方沒有數據發送時,馬上關閉連接,也就將第二步的ack與第三步的fin合并為一步了,這個優化在RFC793 3.5節: ``` CLOSE is an operation meaning "I have no more data to send." The notion of closing a full-duplex connection is subject to ambiguous interpretation, of course, since it may not be obvious how to treat the receiving side of the connection. We have chosen to treat CLOSE in a simplex fashion. The user who CLOSEs may continue to RECEIVE until he is told that the other side has CLOSED also. Thus, a program could initiate several SENDs followed by a CLOSE, and then continue to RECEIVE until signaled that a RECEIVE failed because the other side has CLOSED. We assume that the TCP will signal a user, even if no RECEIVEs are outstanding, that the other side has closed, so the user can terminate his side gracefully. A TCP will reliably deliver all buffers SENT before the connection was CLOSED so a user who expects no data in return need only wait to hear the connection was CLOSED successfully to know that all his data was received at the destination TCP. Users must keep reading connections they close for sending until the TCP says no more data.\[Page 37\] ``` >**注意,在我們準備退出這個tcp連接的時候,我們不能使用ctrl+c退出,不然會出現只能退出一半這種尷尬的情景。請分別在對話兩端ctrl+d**, ## TCP半關閉狀態 TCP是雙全工,所以它允許兩個方向的數據傳輸被獨立關閉。通信的一端可以發送結束報文段給對方,告訴它本端已經完成了數據的發送,但允許繼續接收來自對方的數據,直到對方也發送結束報文段以關閉連接。TCP連接的這種狀態稱為半關閉狀態。 >服務器和客戶端應用程序判斷對方是否已經關閉連接的方法是:read系統調用返回0(收到結束報文段)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看