Python 基於 TCP 傳輸協議的網路通訊實現

一枚大果殼發表於2022-02-22

1、基礎概念

什麼是網路程式設計?

指在網路環境中,如何實現不在同一物理位置中的計算機之間進行資料通訊

 

如果要保證資料通訊順利完成,則需要先了解如下幾個概念:

1.1 協議

不同計算機內的程式之間進行資料通訊時,需要先對資料進行封裝或打包後方可以進行傳輸。所謂協議指通訊雙方需要共同遵守的資料打包格式。

如同現實世界裡郵寄商品一樣:

  1. 商品相當於要傳送給對方的資料:在傳輸之前,需要商品擁有者對商品進行打包,並在打包時填寫上收件人地址、收什人姓名、發件人地址……這是第一次封裝,在此次封裝過程中遵守的打包格式是由商品打包者完成,這層打包標準可稱為應用層標準或應用層協議
  2. 包裹會被物流公司收納,物流公司每天會收到需要傳送至全國各地的包裹,所以,需要再次進行分檢,把傳送至同一個地區的包裹收納在一起,並再次進行打包,並按相應的標準進行資訊填寫。可認為第二次打包的標準是郵局標準或郵局協議.
  3. 郵局打包後的包裹會傳送至相關的運輸部門,運輸部門會把從不同郵局收集來的包裹按目的地進行歸類打包,再選擇不同運輸工具進行傳輸,可選擇飛機、貨車、火車……這次打包協議可稱為傳輸層協議。

 

 

協議是保證資料能被正確傳輸出去的第一操作要素,網際網路上所遵守的協議規範稱為 TCP/IP 協議。

 

1.2 IP 地址

在網路環境中,需要為每一臺計算機指定一個地址,這個地址叫 IP 地址,其實 IP 地址是一個邏輯地址,而每一臺計算機還有一個實體地址,便是網路卡上的 MAC 地址。

IP 地址和 MAC 地址的區別?

  • MAC 地址相當於你我的身份證號碼,是固定、不變的。
  • IP 地址相當於你我現在處於的落腳地址.有的人在一年之內,可能會在不同城市工作,也就意味著邏輯地址是可以有多個的。

1.3 埠

一臺計算機上可以安裝多款網路軟體,如 QQ、瀏覽器、網路遊戲……

作業系統如何區分同一時刻自於網路的多個資料應該交給哪一個軟體處理?

埠相當於作業系統為每一個網路軟體分配的一個門牌識別符號號,用來把從網路上輸入進來的多資料流正確的分流到對應的程式。

當一臺計算機向另一臺計算機傳送資料時:

  1. 首先對資料按協議格式進行打包
  2. 另需要知道對方計算機的地址且還要知道對應程式所監聽的埠號.IP+埠號也稱為套接字,或叫 socket

有點類似於拜訪朋友時:

先封裝一個禮物盒

然後根據朋友告訴自己的地址和門牌號前去拜訪

2、TCP 網路程式設計實現

TCP 是一種傳輸層協議,是可靠的面向連線的傳輸層協議.

2.1 伺服器端程式設計

定義一個函式用來進行具體的資料互動,由子執行緒呼叫.

import socket   # socket 模組
import  time  #時間模組
import  threading  #執行緒模組
def session(sock, addr):
    print('歡迎新 %s:%s...' % addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        # 解碼資料
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('來自於 %s:%s 連線被關閉.' % addr)

 

建立 socket 監聽物件:

 

#建立 TCP socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#監聽埠
server.bind(('127.0.0.1',1234))
server.listen(5)
print('伺服器正在等待客戶的連線……')

建立服務監聽套接字,需要指定服務型別:

socket.AF_UNIX

只能夠用於單一的Unix系統程式間通訊

socket.AF_INET

伺服器之間網路通訊

socket.AF_INET6

IPv6

socket.SOCK_STREAM

流式socket , for TCP

socket.SOCK_DGRAM

資料包式socket , for UDP

socket.SOCK_RAW

原始套接字,普通的套接字無法處理ICMP、IGMP等網路報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由使用者構造IP頭。

socket.SOCK_SEQPACKET

可靠的連續資料包服務

 
while True:
    # 接受一個新連線:
    sock, addr = s.accept()
    # 建立新執行緒來處理TCP連線:
    t = threading.Thread(target=session, args=(sock, addr)) t.start()

 

當有客戶連線後,啟動執行緒完成具體的資料處理.

2.2 客戶端程式設計

客戶端程式碼相對而言較簡單.

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連線:
client.connect(('127.0.0.1', 1234))
# 接收歡迎訊息:
print(client.recv(1024).decode('utf-8'))
for data in [b'Rose', b'Think', b'Babala']:
    # 傳送資料:
    s.send(data)
    print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()

 

測試結果 :

伺服器端

客戶端:

 

3 總結

Python 提供了相關的模組,封裝了底層的具體程式碼邏輯,對於開發者而言,只需要按流程按部就班就可以,如果需要更好的理解整個網路通訊的過程,則需要了解相關的網路知識. 

相關文章