1. 程式人生 > >python高階4.網路 -tcp

python高階4.網路 -tcp

1.TCP簡介

1.1TCP介紹

TCP協議,傳輸控制協議(英語:Transmission Control Protocol,縮寫為 TCP)是一種面向連線的、可靠的、基於位元組流的傳輸層通訊協議,由IETF的RFC 793定義。

TCP通訊需要經過建立連線、資料傳送、終止連線三個步驟。

TCP通訊模型中,在通訊開始之前,一定要先建立相關的連結,才能傳送資料,類似於生活中,“打電話”"

1.2TCP特點

1.2.1面向連線

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

雙方間的資料傳輸都可以通過這一個連線進行。

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

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

1.2.2可靠傳輸

1)TCP採用傳送應答機制

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

2)超時重傳

傳送端發出一個報文段之後就啟動定時器,如果在定時時間內沒有收到應答就重新發送這個報文段。

TCP為了保證不發生丟包,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然後接收端實體對已成功收到的包發回一個相應的確認(ACK);如果傳送端實體在合理的往返時延(RTT)內未收到確認,那麼對應的資料包就被假設為已丟失將會被進行重傳。

3)錯誤校驗

TCP用一個校驗和函式來校驗資料是否有錯誤;在傳送和接收時都要計算 校驗和。

4)流量控制和阻塞管理

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

TCP與UDP的不同點

面向連線(確認有建立三方交握,連線已建立才作傳輸。)
有序資料傳輸
重發丟失的資料包
捨棄重複的資料包
無差錯的資料傳輸
阻塞/流量控制

udp通訊模型

udp通訊模型中,在通訊開始之前,不需要建立相關的連結,只需要傳送資料即可,類似於生活中,“寫信”"
在這裡插入圖片描述
在這裡插入圖片描述
TCP通訊模型

udp通訊模型中,在通訊開始之前,一定要先建立相關的連結,才能傳送資料,類似於生活中,“打電話”"
在這裡插入圖片描述


2.tcp網路程式-客戶端

tcp客戶端,並不是像之前一個段子:一個顧客去飯館吃飯,這個顧客要點菜,就問服務員咱們飯店有客戶端麼,然後這個服務員非常客氣的說道:先生 我們飯店不用客戶端,我們直接送到您的餐桌上。

如果,不學習網路的知識是不是 說不定也會發生那樣的笑話 ,哈哈。

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

TCP客戶端構建流程

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

示例程式碼:
from socket import *
#建立socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)

#目的資訊
server_ip = input(“請輸入伺服器ip:”)
server_port = int(input(“請輸入伺服器port:”))

#連結伺服器
tcp_client_socket.connect((server_ip, server_port))

#提示使用者輸入資料
send_data = input(“請輸入要傳送的資料:”)

tcp_client_socket.send(send_data.encode(“gbk”))

#接收對方傳送過來的資料,最大接收1024個位元組
recvData = tcp_client_socket.recv(1024)
print(‘接收到的資料為:’, recvData.decode(‘gbk’))

#關閉套接字
tcp_client_socket.close()

執行流程:
<1>tcp客戶端
請輸入伺服器ip:10.10.0.47
請輸入伺服器port:8080
請輸入要傳送的資料:你好啊
接收到的資料為: 我很好,你呢

<2>網路除錯助手:
在這裡插入圖片描述
3.TCP伺服器

生活中的電話機
如果想讓別人能夠打通咱的電話獲取相應服務的話,需要做以下幾件事情:
1.買個手機
2.插上手機卡
3.設計手機為正常接聽狀態
4.靜靜等這別人撥打

TCP伺服器

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

from socket import *

#建立socket
tcp_server_socket = socket(AF_INET, SOCK_STREAM)

#本地資訊
address = (’’, 7788)

#繫結
tcp_server_socket.bind(address)

#使用socket建立的套接字預設的屬性是主動的,使用listen將其變為被動的,這樣就可以接收別人的連結了
tcp_server_socket.listen(128)

#如果有新的客戶端來連結伺服器,那麼就產生一個新的套接字專門為這個客戶端服務
#client_socket用來為這個客戶端服務
#tcp_server_socket就可以省下來專門等待其他新客戶端的連結
client_socket, clientAddr = tcp_server_socket.accept()

#接收對方傳送過來的資料
recv_data = client_socket.recv(1024) # 接收1024個位元組
print(‘接收到的資料為:’, recv_data.decode(‘gbk’))

#傳送一些資料到客戶端
client_socket.send(“thank you !”.encode(‘gbk’))

#關閉為這個客戶端服務的套接字,只要關閉了,就意味著為不能再為這個客戶端服務了,如果還需要服務,只能再次重新連線
client_socket.close()

執行流程:
<1>tcp伺服器
接收到的資料為:你在麼?

<2>網路除錯助手:
在這裡插入圖片描述

4.TCP注意點

1.tcp伺服器一般情況下都需要繫結,否則客戶端找不到這個伺服器

2.tcp客戶端一般不繫結,因為是主動連結伺服器,所以只要確定好伺服器的ip、port等資訊就好,本地客戶端可以隨機,對於同一個程式可以採用隨機port開啟多個視窗

3.tcp伺服器中通過listen可以將socket創建出來的主動套接字變為被動的,這是做tcp伺服器時必須要做的

4.當客戶端需要連結伺服器時,就需要使用connect進行連結,udp是不需要連結的而是直接傳送,但是tcp必須先連結,只有連結成功才能通訊

5.當一個tcp客戶端連線伺服器時,伺服器端會有1個新的套接字,這個套接字用來標記這個客戶端,單獨為這個客戶端服務

6.listen後的套接字是被動套接字,用來接收新的客戶端的連結請求的,而accept返回的新套接字是標記這個新客戶端的

7.關閉listen後的套接字意味著被動套接字關閉了,會導致新的客戶端不能夠連結伺服器,但是之前已經連結成功的客戶端正常通訊。

8.關閉accept返回的套接字意味著這個客戶端已經服務完畢

(重要)9.當客戶端的套接字呼叫close後,伺服器端會recv解堵塞,並且返回的長度為0,因此伺服器可以通過返回資料的長度來區別客戶端是否已經下線

5.案例:檔案下載器

總結:流程圖

udp:
socket
bind
sendto/recvfrom
close

tcp client:
socket
connect()
send/recv
close

tcp:
socket
bind()
listen
accept()
recv/send
close