級別: ★★☆☆☆
標籤:「TCP」「三次握手」「數據傳輸」「四次揮手」
做者: WYW
審校: QiShare團隊php
筆者最近看了關於Python的部份內容,發現網絡編程部分很是容易可以建立一個本地TCP服務器,正好能夠用來分析一下TCP的請求和響應過程。 在本篇文章,筆者將給你們介紹下TCP創建鏈接(三次握手),傳輸數據,斷開鏈接(四次揮手)的過程。html
TCP:TCP(Transmission Control Protocol 傳輸控制協議)是一種面向鏈接的
、可靠的
、基於字節流
的傳輸層通訊協議
,由IETF的RFC 793定義。python
聊到網絡協議,咱們經常會想到OSI(Open System Interconnection 開放式系統互聯)七層模型、TCP/IP協議簇,她位於OSI、TCP/IP協議簇哪一層等問題。 以下圖OSI七層模型及對應的TCP/IP協議簇所示,TCP位於OSI中的第四層(傳輸層)。位於TCP/IP協議簇中的第四層(TCP or UDP)。git
下圖爲OSI七層模型及對應的TCP/IP協議簇
github
面向鏈接
的,是指客戶端在發送、接收數據以前須要先創建鏈接,這個鏈接過程須要三次握手
來完成,筆者藉助Python搭建了一個本地的TCP服務,並使用Wireshark(Wireshark(前稱Ethereal)是一個網絡封包分析軟件。網絡封包分析軟件的功能是擷取網絡封包,並儘量顯示出最爲詳細的網絡封包資料。 )捕獲了本地的TCP服務器和TCP客戶端之間請求響應的過程,帶你們一塊兒看一下創建鏈接(三次握手),傳輸數據,斷開鏈接(四次揮手)的過程。筆者在前文提到了要用Python建立一個本地TCP服務器,而且分析TCP的請求響應過程。這裏筆者使用的是PythonIDE、Mac自帶的終端簡單建立了一個本地TCP服務端和客戶端。編程
筆者會分析的過程以下:
-> 建立而且啓動一個端口號爲20000的TCP服務端
-> 建立客戶端並和服務端創建鏈接(三次握手)
-> 客戶端向服務端發送數據'AB'
-> 服務端到數據後給客戶端發送數據'AB'
-> 服務端收到數據向客戶端發送收到的數據(當前即'AB')
-> 客戶端和服務端斷開鏈接(四次揮手)
-> 使用Wireshark對創建鏈接(三次握手),傳輸數據,斷開鏈接(四次揮手)的過程進行分析
服務端代碼:bash
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license()" for more information.
>>> from socketserver import BaseRequestHandler, TCPServer
>>> class EchoHandler(BaseRequestHandler):
def handle(self):
print('Got connection from', self.client_address)
while True:
msg = self.request.recv(8192)
if not msg:
break
self.request.send(msg)
>>> if __name__ == '__main__':
serv = TCPServer(('', 20000), EchoHandler)
serv.serve_forever()
Got connection from ('127.0.0.1', 59006)
複製代碼
客戶端代碼:服務器
wangyongwangdeiMac:~ wangyongwang$ python
Python 2.7.15 (default, Oct 2 2018, 11:47:18)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import socket, AF_INET, SOCK_STREAM
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.connect(('localhost', 20000))
複製代碼
上述代碼的效果以下圖所示: 微信
如上圖,Got connection from ('127.0.0.1', 62515)咱們能夠肯定客戶端使用的端口是59006
。網絡
經過上述準備工做,下邊筆者會使用Wireshark捕獲TCP請求響應的整個過程,並進行相應分析。
對上圖中的代號及下文中的代號作說明:
Seq
即下文中的Sequence number
,序列號是指發送數據的位置。每發送一次數據,就累加一次該數據字節數的大小。通常用Wireshark捕獲咱們平時的請求的Seq是一個隨機數。Ack
即Acknowledgement number
,是指下一次應該受到的數據的序列號。SYN
爲Flags部分的Syn
,Syn爲1表示但願創建鏈接。ACK
爲Flags部分的ACK
,Ack爲1表示確認應答的字段變爲有效。TCP第一次握手,客戶端向服務端發送報文,關鍵信息爲Syn=1,Seq=0。以下圖所示,sequence number= x = 0,Syn=1。
TCP第二次握手,服務端向客戶端發送報文,關鍵信息爲Ack=x+1=1,Syn=1,Seq=y=0。以下圖所示,sequence number=y=0,Ack=x+1=1 , Syn = 1。
TCP第三次握手,客戶端向服務端發送報文,Seq=x+1=1,Ack=y+1=1,ACK=1。以下圖所示,Seq=x+1=1,Ack=y+1=1,ACK=1。
咱們能夠發如今三次握手以後,還有一次TCP Window Update。
TCP Window Update 是TCP通訊中的一個狀態,它能夠發生的緣由有不少,但最終歸結於發送者傳輸數據的速度比接收者讀取的數據還快,這使得接受端的在緩衝區必須釋放一部分空間來裝發送過來的數據,而後
向發送者
發送Windows Update,告訴給發送者應該以多大的速度發送數據,從而使得數據傳輸與接受恢復正常。參考:tcp三次握手
從上圖TCP Window Update,根據Source Port:20000及Destination Port:59006可知,當前發送者是客戶端
,解釋下上一段文字的意思是,客戶端發送的數據太快,服務端讀書數據慢,服務端向客戶端發送了一個TCP Window Update的報文。
上述內容就是TCP創建鏈接的過程,下邊筆者給你們介紹下傳輸數據部分的內容:
查看數據傳輸過程和以前創建鏈接部分,用的是下圖代碼進行的分析:
代碼內容和以前創建鏈接的代碼同樣,只是添加了發送數據
和
斷開鏈接
的幾行代碼。可見此次客戶端分配的端口號爲
53262
。 在分析數據傳輸過程以前,筆者先對下邊會用到的名詞及工具作個簡單說明:
字節
即byte
,比特
即bit
,1個字節(byte)=8個比特(bit)。
ASCII碼:是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其餘西歐語言。它是現今最通用的單字節編碼系統
舉個例子'A'的ASCII碼爲0x41
基本的16進制、2進制、10進制之間的轉換:
16進制0x41對應2進製爲 0100 0001對應10進製爲4 * 16 + 1 = 65
下邊筆者帶你們看一下數據傳輸部分的分析:
下圖表示客戶端s.send(b'A')以二進制形式傳輸'A'(其對應的ASCII碼爲65)傳輸過程,:
下邊展現一個客戶端s.send(b'AB')而且服務端給予相應的迴應(服務端也給客戶端發送收到的'')的過程
從源端口53262
,目的端口20000
能夠看出,下圖表示客戶端向服務端發送消息
,發送的數據爲'AB','AB'的ASCII碼爲0x4142。
源端口20000
,
目的端口53262
能夠看出下圖表示
服務端向客戶端反饋
收到了消息。Acknowledgement number 爲4是由於,服務端接接收了客戶端的2個字節的數據,在以前的客戶端的Sequence number的基礎上加了2。
從
源端口20000
,
目的端口53262
能夠看出,下圖表示
服務端向客戶端發送消息
,發送的數據爲'AB','AB'的ASCII碼爲0x4142。
從
源端口53262
,
目的端口20000
能夠看出下圖表示
客戶端向服務端反饋
收到了消息。Acknowledgement number 爲4是由於,客戶端接收了服務端的2個字節的數據,在以前的服務端的Sequence number的基礎上加了2。
TCP斷開鏈接示意圖以下:
對應的Python的客戶端代碼s.shutdown(2),客戶端主動斷開鏈接的。
響應的Wireshark抓包分析以下: TCP斷開鏈接第一次揮手,從源端口53262到目的端口20000
,能夠看出是客戶端主動斷開鏈接的。Flags中的Fin是設置爲1的,Sequence number爲7。
TCP斷開鏈接第二次揮手,從源端口20000到目的端口53262
,能夠看出是服務端給予客戶端斷開鏈接的響應
。而且Acknowledge number對以前的客戶端的Sequence number作了加1操做。
源端口20000到目的端口53262
,Flags中的Fin是設置爲1的,能夠看出是
服務端向客戶端發送斷開鏈接的
。Sequence number爲7。
TCP斷開鏈接第四次揮手,從
源端口53262到目的端口20000
,能夠看出是
客戶端給予服務端斷開鏈接的響應
。而且Acknowledge number對以前的服務端的Sequence number作了加1操做。
下邊,筆者貼出了IP和TCP首部及Wireshark捕獲TCP請求過程的的圖。有興趣的讀者可自行作簡單分析。
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
iOS 多線程之GCD
iOS 多線程之NSOperation
iOS 多線程之NSThread
iOS Winding Rules 纏繞規則
iOS 簽名機制
iOS 掃描二維碼/條形碼
奇舞週刊