python網路-Socket之TCP編程(26)

来源:https://www.cnblogs.com/Se7eN-HOU/archive/2019/05/22/10903528.html
-Advertisement-
Play Games

一、TCP簡介 1、TCP介紹 TCP協議,傳輸控制協議(英語:Transmission Control Protocol,縮寫為 TCP)是一種面向連接的、可靠的、基於位元組流的傳輸層通信協議。 TCP通信需要經過創建連接、數據傳送、終止連接三個步驟。 TCP通信模型中,在通信開始之前,一定要先建立 ...


一、TCP簡介

1、TCP介紹

TCP協議,傳輸控制協議(英語:Transmission Control Protocol,縮寫為 TCP)是一種面向連接的、可靠的、基於位元組流的傳輸層通信協議。

TCP通信需要經過創建連接、數據傳送、終止連接三個步驟。

TCP通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送數據,類似於生活中,"打電話"。

2、TCP面向連接

通信雙方必須先建立連接才能進行數據的傳輸,雙方都必須為該連接分配必要的系統內核資源,以管理連接的狀態和連接上的傳輸。

雙方間的數據傳輸都可以通過這一個連接進行。

完成數據交換後,雙方必須斷開此連接,以釋放系統資源。

這種連接是一對一的,因此TCP不適用於廣播的應用程式,基於廣播的應用程式請使用UDP協議。

3、TCP可靠傳輸

1)TCP採用發送應答機制

TCP發送的每個報文段都必須得到接收方的應答才認為這個TCP報文段傳輸成功

2)超時重傳

發送端發出一個報文段之後就啟動定時器,如果在定時時間內沒有收到應答就重新發送這個報文段。TCP為了保證不發生丟包,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然後接收端實體對已成功收到的包發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那麼對應的數據包就被假設為已丟失將會被進行重傳。

3)錯誤校驗

TCP用一個校驗和函數來檢驗數據是否有錯誤;在發送和接收時都要計算校驗和。

4) 流量控制和阻塞管理

流量控制用來避免主機發送得過快而使接收方來不及完全收下。

4、TCP與UDP的不同點

  • 面向連接(確認有創建三方交握,連接已創建才作傳輸。)
  • 有序數據傳輸
  • 重發丟失的數據包
  • 捨棄重覆的數據包
  • 無差錯的數據傳輸
  • 阻塞/流量控制

 

二、TCP數據包格式

所謂三次握手(Three-way Handshake),是指建立一個TCP連接時,需要客戶端和伺服器總共發送3個數據包

那麼我們就先來看一下TCP數據包的格式:

 

在TCP層,有個FLAGS欄位,這個欄位有以下幾個標識:SYN, FIN, ACK, PSH, RST, URG.
  • URG—為1表示高優先順序數據包,緊急指針欄位有效。
  • ACK—為1表示確認號欄位有效
  • PSH—為1表示是帶有PUSH標誌的數據,指示接收方應該儘快將這個報文段交給應用層而不用等待緩衝區裝滿。
  • RST—為1表示出現嚴重差錯。可能需要重現創建TCP連接。還可以用於拒絕非法的報文段和拒絕連接請求。
  • SYN—為1表示這是連接請求或是連接接受請求,用於創建連接和使順序號同步
  • FIN—為1表示發送方沒有數據要傳輸了,要求釋放連接
  • Seq---序號,這是為了連接以後傳送數據用的,
  • Ack---確認號對收到的數據包的確認,值是等待接收的數據包的序列號+1。

 

三、TCP的三次握手

三次握手的目的是連接伺服器指定埠,建立TCP連接,並同步連接雙方的序列號和確認號並交換 TCP 視窗大小信息.在socket編程中,客戶端執行connect()時。將觸發三次握手。

三次握手示意圖

第一次握手:(Client向Server發送聯機請求)

SYN=1(Client向Server發送聯機請求)

Client想要與Server進行TCP通信,首先他需要向Server發送一個SYN=1的同步序列編號(syncsynchronized squsequence number)用來表示建立連接,並且隨機產生一個數Seq number = X的數據包到Server,Server由於SYN=1知道,Client要求建立聯機,到這裡第一次握手就結束了

第二次握手:(Server向Client回覆聯機並確認聯機信息)

SYN=1(Server接受Client的聯機請求)

ACK=1(確認信息)

這是對第一次握手信息的確認,表示Server收到了Client的第一次握手信息

Ack=X+1(確認回覆)

同時Server回覆Client一個確認碼Ack表示你的聯機請求我已經收到,而且數據沒有丟失,怎麼驗證數據沒有丟失呢?即Ack的值等於Client發過來Seq的值加1,即Ack = X+1。因為我都知道你發過來的Seq的值,所以這個數據包沒有丟失。

Seq = Y(第二次握手的數據包序列號)

Server給Client的數據包序列號,為了數據包在到達Client之後的驗證,所以這次從Server到Client的數據包中同樣也會隨機產生一個Seq number = Y,

第三次握手

ACK=1(對第二次握手的確認)

首先Client會打開Server發送過來的Ack驗證一下是否正確為Seq+1,即第一次發送的seq number+1,確認無誤後,Client仍然需要給Server再次回覆確認即ACK=1

Seq=Z(第三次握手的數據包序列號)

Ack=Y+1

Client告訴Server,你給我回覆的信息我也收到了,怎麼確定我收到了你的信息呢?就是通過Ack等於第二次握手傳遞過來的Seq值+1。到此為止三次握手結束進入ESTABLISHED狀態,開始進行數據傳輸。

 

四、TCP四次揮手

 

第一次揮手發送FIN請求,第一次揮手結束。

第二次揮手開始,被動方向主動方發送ACK確認碼,到這裡第二次揮手結束。

第三次握手開始被動方向主動方發送FIN號結束。

第四次揮手開始主動方向被動方發送ACK確認,等待2MSL後斷開TCP連接。

 

五、TCP的十種狀態

這十種狀態分別是三次握手和四次揮手中的狀態,在上面兩個圖中都給大家標記出來了,這裡再給大家一個簡單的圖表示

 

六、TCP的2MSL問題

在四次揮手中我們提到了時間等待狀態,等待的時間是2MSL。

2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱為2MSL等待狀態,

當TCP的一端發起主動關閉,在發出最後一個ACK包後,即第3次揮手完成後發送了第四次揮手的ACK包後就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間,等待2MSL時間主要目的是怕最後一個 ACK包對方沒收到,那麼對方在超時後將重發第三次揮手的FIN包,主動關閉端接到重發的FIN包後可以再發一個ACK應答包。在TIME_WAIT狀態時兩端的埠不能使用,要等到2MSL時間結束才可繼續使用。當連接處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設置 SO_REUSEADDR選項達到不必等待2MSL時間結束再使用此埠。

 

七、TCP長連接和短連接

TCP在真正的讀寫操作之前,server與client之間必須建立一個連接,

當讀寫操作完成後,雙方不再需要這個連接時它們可以釋放這個連接,

連接的建立通過三次握手,釋放則需要四次握手,

所以說每個連接的建立都是需要資源消耗和時間消耗的。

1. TCP短連接

模擬一種TCP短連接的情況:

  1. client 向 server 發起連接請求
  2. server 接到請求,雙方建立連接
  3. client 向 server 發送消息
  4. server 回應 client
  5. 一次讀寫完成,此時雙方任何一個都可以發起 close 操作

在第 步驟5中,一般都是 client 先發起 close 操作。當然也不排除有特殊的情況。從上面的描述看,短連接一般只會在 client/server 間傳遞一次讀寫操作!

2. TCP長連接

再模擬一種長連接的情況:

  1. client 向 server 發起連接
  2. server 接到請求,雙方建立連接
  3. client 向 server 發送消息
  4. server 回應 client
  5. 一次讀寫完成,連接不關閉
  6. 後續讀寫操作...
  7. 長時間操作之後client發起關閉請求

3. TCP長/短連接操作過程

(1)短連接的操作步驟是:建立連接——數據傳輸——關閉連接...建立連接——數據傳輸——關閉連接

(2) 長連接的操作步驟是:建立連接——數據傳輸...(保持連接)...數據傳輸——關閉連接

4. TCP長/短連接的優點和缺點

  • 長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間。對於頻繁請求資源的客戶來說,較適用長連接。

  • client與server之間的連接如果一直不關閉的話,會存在一個問題,隨著客戶端連接越來越多,server早晚有扛不住的時候,這時候server端需要採取一些策略,如關閉一些長時間沒有讀寫事件發生的連接,這樣可以避免一些惡意連接導致server端服務受損;如果條件再允許就可以以客戶端機器為顆粒度,限制每個客戶端的最大長連接數,這樣可以完全避免某個蛋疼的客戶端連累後端服務。

  • 短連接對於伺服器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段。但如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬。

5. TCP長/短連接的應用場景

  • 長連接多用於操作頻繁,點對點的通訊,而且連接數不能太多情況。每個TCP連接都需要三次握手,這需要時間,如果每個操作都是先連接,再操作的話那麼處理速度會降低很多,所以每個操作完後都不斷開,再次處理時直接發送數據包就OK了,不用建立TCP連接。

    例如:資料庫的連接用長連接,如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。

  • 而像WEB網站的http服務一般都用短鏈接,因為長連接對於服務端來說會耗費一定的資源,而像WEB網站這麼頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以併發量大,但每個用戶無需頻繁操作情況下需用短連好。

 

八、TCP的通信模型

tcp通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送數據,類似於生活中,"打電話"

生活中的電話機,如果想讓別人能更夠打通咱們的電話獲取相應服務的話,需要做一下幾件事情:

  1. 買個手機
  2. 插上手機卡
  3. 設計手機為正常接聽狀態(即能夠響鈴)
  4. 靜靜的等著別人撥打

tcp伺服器如同上面的電話機過程一樣,在程式中,如果想要完成一個tcp伺服器的功能,需要的流程如下:

  1. 創建一個socket套接字
  2. bind綁定ip和port
  3. listen使套接字變為可以被動鏈接
  4. accept等待客戶端的鏈接
  5. recv/send接收發送數據

 

九、TCP伺服器代碼實現

#coding = utf-8
from socket import *
#1、創建socket套接字
tcpServerSocket = socket(AF_INET,SOCK_STREAM)
#2、綁定本地信息
address = ("",7788)
tcpServerSocket.bind(address)
#3、使用socket創建的套接字預設的屬性是主動的,使用listen將其變為被動,這樣就可以等著別人鏈接了
tcpServerSocket.listen(5)

"""
如果有新的客戶端來鏈接伺服器,那麼就產生一個新的套接字專門為這個客戶端伺服器
newSocket用來為這個客戶端服務
tcpServerSocket就可以省下來專門等待其他的客戶端的鏈接
"""
newSocket,clientAddress = tcpServerSocket.accept()

#4、接收對象發送過來的數據,最大接收1024個位元組
reveiveData = newSocket.recv(1024)
print("接收的數據為:%s"%reveiveData.decode())

#5、發送數據到客戶端
newSocket.send("haha".encode())

#6、關閉為這個客戶端服務的套接字
newSocket.close()

#7、關閉監聽套接字
tcpServerSocket.close()

運行流程

1、TCP伺服器

2、網路調試助手:

 

十、TCP客戶端代碼實現

所謂的伺服器端:就是提供服務的一方,而客戶端,就是需要被服務的一方

tcp的客戶端要比伺服器端簡單很多,如果說伺服器端是需要自己買手機、查手機卡、設置鈴聲、等待別人打電話流程的話,那麼客戶端就只需要找一個電話亭,拿起電話撥打即可,流程要少很多

#coding = utf-8
from socket import *

#1、創建socket
tcpClientSocket = socket(AF_INET,SOCK_STREAM)

#2、鏈接伺服器
serverAddress = ("192.168.100.106",7788)
tcpClientSocket.connect(serverAddress)

#3、向伺服器發送數據
tcpClientSocket.send("哈哈".encode("gb2312"))

#4、接收對方發送過來的數據,最大接收1024個位元組
receiveData = tcpClientSocket.recv(1024)
print("接收到的數據為%s"%receiveData.decode("gb2312"))

#5、關閉套接字
tcpClientSocket.close()

運行流程:

1、tcp客戶端

2、網路調試助手:

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 工作之餘在知乎上偶然看到一篇回帖,瞬間覺得之前看的那麼多資料都不及這一篇讓我對 websocket 的認知深刻易懂,之前看總完總覺得一知半解雲里霧裡。所以與大家共同分享一下一起學習。比較喜歡這種博客理論和小故事的事例結合,讀起來很輕鬆,不枯燥。廢話不多說了,進入正題了~ 一、websocket與ht ...
  • 發佈與訂閱消息系統 在正式討論Apache Kafka (以下簡稱Kafka)之前,先來瞭解發佈與訂閱消息系統的概念, 並認識這個系統的重要性。數據(消息)的發送者(發佈者)不會直接把消息發送給接收 者,這是發佈與訂閱消息系統的一個特點。發佈者以某種方式對消息進行分類,接收者 (訂閱者)訂閱它們,以 ...
  • [toc] 這篇文章主要講 map 的賦值、刪除、查詢、擴容的具體執行過程,仍然是從底層的角度展開。結合源碼,看完本文一定會徹底明白 map 底層原理。 我要說明的是,這裡對 map 的基本用法涉及比較少,我相信可以通過閱讀其他入門書籍瞭解。本文的內容比較深入,但是由於我畫了各種圖,我相信很容易看懂 ...
  • JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? 1. Java虛擬機記憶體的五大區域 Java的運行離不開Java虛擬機的支持,今天我就跟大家探討一下Java ...
  • 厲害了,2019/05/21 Apache軟體基金會發表博文,宣佈 Dubbo 在 2019/05/20 這天正式畢業,成為 Apache 的頂級項目。 參考:https://blogs.apache.org/foundation/entry/the apache software foundati ...
  • 14.1 基本介紹 -Scala飾運行在Java虛擬機(Java Virtual Machine)之上,因此具有如下特點 1) 輕鬆實現和豐富的Java類庫互聯互通 2) 它既支持面向對象的編程方式,又支持函數式編程 3) 它寫出的程式像動態語言一樣簡潔,但事實上它確是嚴格意義上的靜態語言 14.2 ...
  • Collection集合 數組的長度是固定的,集合的長度是可變的 數組中存儲的是同一類型的元素,可以存儲基本數據類型值。集合存儲的都是對象。而且對象的類型可以不一致。 集合框架 java import java.util. ; public class IteratorDemo{ public st ...
  • 111
    1. 內容大綱 1. 自定義模塊 2. 模塊是什麼? 3. 為什麼要有模塊? 什麼是腳本? 4. 模塊的分類 5. import的使用 第一次導入模塊執行三件事 被導入模塊有獨立的名稱空間 為模塊起別名 導入多個模塊 6. from ... import ... from ... import .. ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...