初探TCP

級別: ★★☆☆☆
標籤:「TCP」「三次握手」「數據傳輸」「四次揮手」
做者: WYW
審校: QiShare團隊php

筆者最近看了關於Python的部份內容,發現網絡編程部分很是容易可以建立一個本地TCP服務器,正好能夠用來分析一下TCP的請求和響應過程。 在本篇文章,筆者將給你們介紹下TCP創建鏈接(三次握手),傳輸數據,斷開鏈接(四次揮手)的過程。html

TCP簡介

  • 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

OSI TCP/IP Family

  • TCP是面向鏈接的,是指客戶端在發送、接收數據以前須要先創建鏈接,這個鏈接過程須要三次握手來完成,筆者藉助Python搭建了一個本地的TCP服務,並使用Wireshark(Wireshark(前稱Ethereal)是一個網絡封包分析軟件。網絡封包分析軟件的功能是擷取網絡封包,並儘量顯示出最爲詳細的網絡封包資料。 )捕獲了本地的TCP服務器和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))
複製代碼

上述代碼的效果以下圖所示: 微信

TCP請求響應效果圖

TCP創建鏈接效果圖

如上圖,Got connection from ('127.0.0.1', 62515)咱們能夠肯定客戶端使用的端口是59006網絡

經過上述準備工做,下邊筆者會使用Wireshark捕獲TCP請求響應的整個過程,並進行相應分析。

TCP三次握手

  • TCP經過三次握手創建鏈接,咱們對下圖應該比較熟悉:
    TCP三次握手圖解

對上圖中的代號及下文中的代號作說明:

  • Seq即下文中的Sequence number ,序列號是指發送數據的位置。每發送一次數據,就累加一次該數據字節數的大小。通常用Wireshark捕獲咱們平時的請求的Seq是一個隨機數。
  • AckAcknowledgement number,是指下一次應該受到的數據的序列號。
  • SYN爲Flags部分的Syn,Syn爲1表示但願創建鏈接。
  • ACK爲Flags部分的ACK,Ack爲1表示確認應答的字段變爲有效。

TCP第一次握手,客戶端向服務端發送報文,關鍵信息爲Syn=1,Seq=0。以下圖所示,sequence number= x = 0,Syn=1。

TCP第一次握手

TCP第二次握手,服務端向客戶端發送報文,關鍵信息爲Ack=x+1=1,Syn=1,Seq=y=0。以下圖所示,sequence number=y=0,Ack=x+1=1 , Syn = 1。

TCP第二次握手

TCP第三次握手,客戶端向服務端發送報文,Seq=x+1=1,Ack=y+1=1,ACK=1。以下圖所示,Seq=x+1=1,Ack=y+1=1,ACK=1。

TCP第三次握手

咱們能夠發如今三次握手以後,還有一次TCP Window Update。

TCP Window Update

TCP Window Update 是TCP通訊中的一個狀態,它能夠發生的緣由有不少,但最終歸結於發送者傳輸數據的速度比接收者讀取的數據還快,這使得接受端的在緩衝區必須釋放一部分空間來裝發送過來的數據,而後向發送者發送Windows Update,告訴給發送者應該以多大的速度發送數據,從而使得數據傳輸與接受恢復正常。參考:tcp三次握手

從上圖TCP Window Update,根據Source Port:20000及Destination Port:59006可知,當前發送者是客戶端,解釋下上一段文字的意思是,客戶端發送的數據太快,服務端讀書數據慢,服務端向客戶端發送了一個TCP Window Update的報文。

上述內容就是TCP創建鏈接的過程,下邊筆者給你們介紹下傳輸數據部分的內容:

TCP的數據傳輸過程:

查看數據傳輸過程和以前創建鏈接部分,用的是下圖代碼進行的分析:

代碼內容和以前創建鏈接的代碼同樣,只是添加了 發送數據斷開鏈接的幾行代碼。可見此次客戶端分配的端口號爲 53262。 在分析數據傳輸過程以前,筆者先對下邊會用到的名詞及工具作個簡單說明:

字節byte比特bit,1個字節(byte)=8個比特(bit)。

ASCII碼:是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其餘西歐語言。它是現今最通用的單字節編碼系統

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')而且服務端給予相應的迴應(服務端也給客戶端發送收到的'')的過程

  • 接收數據的部分Flags中的Acknowledgement 設置爲1,表示確認應答的字段有效
  • 接收數據的部分Flags中的Push 設置爲1表示表示接收方應該儘快把數據傳給上層應用協議

源端口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斷開鏈接四次揮手

TCP斷開鏈接示意圖以下:

TCP斷開鏈接示意圖

對應的Python的客戶端代碼s.shutdown(2),客戶端主動斷開鏈接的。

  • 斷開鏈接的Flags中Fin是設置爲1的,表示但願斷開鏈接。
  • 斷開鏈接的Flags中Ack是設置爲1的,表示確認應答字段有效。

響應的Wireshark抓包分析以下: TCP斷開鏈接第一次揮手,從源端口53262到目的端口20000,能夠看出是客戶端主動斷開鏈接的。Flags中的Fin是設置爲1的,Sequence number爲7。

TCP斷開鏈接第一次揮手

TCP斷開鏈接第二次揮手,從源端口20000到目的端口53262,能夠看出是服務端給予客戶端斷開鏈接的響應。而且Acknowledge number對以前的客戶端的Sequence number作了加1操做。

TCP斷開鏈接第二次揮手
TCP斷開鏈接第三次揮手,從 源端口20000到目的端口53262,Flags中的Fin是設置爲1的,能夠看出是 服務端向客戶端發送斷開鏈接的。Sequence number爲7。
TCP斷開鏈接第三次揮手
TCP斷開鏈接第四次揮手,從 源端口53262到目的端口20000,能夠看出是 客戶端給予服務端斷開鏈接的響應。而且Acknowledge number對以前的服務端的Sequence number作了加1操做。
TCP斷開鏈接第四次揮手

下邊,筆者貼出了IP和TCP首部及Wireshark捕獲TCP請求過程的的圖。有興趣的讀者可自行作簡單分析。

TCP數據在IP數據報中的封裝及TCP包首部

  • 後來和昆哥一塊兒交流,通過昆哥指正,上圖的TCP首部已經更新過了,較新的TCP首部格式以下:
    TCP首部
    下圖爲TCP首部中的控制位部分
    控制位 Control Flag

TCP

TCP

參考內容:


小編微信:可加並拉入《QiShare技術交流羣》。

關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)

推薦文章:
iOS 多線程之GCD
iOS 多線程之NSOperation
iOS 多線程之NSThread
iOS Winding Rules 纏繞規則
iOS 簽名機制
iOS 掃描二維碼/條形碼
奇舞週刊

相關文章
相關標籤/搜索