Socket(套接字)
介紹 UDP 和 TCP 協議之前,先熟悉下 socket 的基本概念,
- 基本概念
Socket 是通信的基石,是支持 TCP/IP 協議的網路通信的基本操作單元,在網路通信程序中端點的一種抽象表示,網路中使用 Socket 傳輸資料是一種特殊的網路 I/O,
- 作業模式
打開open -> 讀寫write/read -> 關閉close
- 五種資訊
socket 包括了資料傳輸必須的五元組,分別為源IP、源埠、目的IP、目的埠和協議號
- 通信機制
基于流(stream)或者基于資料報(datagram)
- python 中使用
import socket
socket.socket(...)
UDP
UDP(User Datagram Protocol) 用戶資料報協議,是一種面向無連接的協議,提供簡單不可靠的資訊傳輸服務,發送后不會確認資訊是否到達,
UDP 通信模型中,在通信開始之前,不需要建立相關的鏈接,只需要發送資料即可,類似于生活中"寫信",
- 使用 socket 使用 UDP 的收發資料,先看原理圖

- 客戶端代碼實作
# 客戶端 發送資料
# 1.創建udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
send_data = https://www.cnblogs.com/izbw/p/input("請輸入要發送的資料:")
if send_data =https://www.cnblogs.com/izbw/p/='exit':
break
# 2.發送資料
udp_socket.sendto(send_data.encode(), ("192.168.1.110", 8080)) # 對方的ip和port
# 3.關閉套接字
udp_socket.close()
- 服務端代碼實作
# 服務端 接收資料
HOST = '' # 空為localhost
PORT = 7788
ADDR = (HOST, PORT)
BUFSIZE = 1024 # 一次接收最大的尺寸
# 1.創建udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.系結本地套接字資訊
udp_socket.bind(ADDR) # 系結必須是本機的ip和port
while True:
# 3.接收資料
data, addr = udp_socket.recvfrom(BUFSIZE) # 回傳接收資料和發送方的地址資訊
if data.decode() == 'exit':
print("退出")
break
# 列印接收的資料
print(f"{addr[0]}:{addr[1]}", data.decode())
# 4.關閉套接字
udp_socket.close()
套接字是可以同時收發資料,是全雙工狀態,在呼叫
recvform之前收到資料,作業系統會將資料暫時儲存起來,等到程式呼叫recvform取出資料,在呼叫recvform之后未接收到資料,程式會進入阻塞狀態,等待資料的到來,
TCP
TCP(Transmission Control Protocol)傳輸控制協議,是一種面向連接的,可靠的、基于位元組流的傳輸層通信協議,
TCP 通信需要經過創建連接、資料傳送、終止連接三個步驟,
TCP 通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送資料,類似于生活中"打電話", 這種連接是一對一的,因此TCP不適用于廣播的應用程式,基于廣播的應用程式請使用 UDP 協議,
特點:
-
面向連接(使用三次握手建立連接,連接已創建才作傳輸,采用四次揮手斷開連接,)
-
有序資料傳輸
-
重發丟失的資料包
-
舍棄重復的資料包
-
無差錯的資料傳輸
-
阻塞/流量控制
使用 socket 實作 TCP 的收發資料,先看原理圖

- 客戶端代碼實作
# 客戶端
IPADDR = "192.168.1.110"
PORT = 7788
# 創建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務器,創建連接
tcp_socket.connect((IPADDR, PORT))
# 收發資料
send_data = https://www.cnblogs.com/izbw/p/input("輸入發送的資料:")
tcp_socket.send(send_data.encode())
# 關閉套接字,關閉連接
tcp_socket.close()
- 服務端代碼實作
# 服務端
IPADDR = “” # 默認localhost
PORT = 7788
BUFSIZE = 1024 # 一次接收最大的尺寸
print('server start...')
# 創建套接字(監聽套接字) =》買個手機
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 系結本地資訊 =》 插入手機卡
tcp_socket.bind((IPADDR, PORT))
# 將手機設為正常,能夠響鈴 =》 讓默認的套接字由主動變為監聽
tcp_socket.listen(128) # 同一時間,最大允許連接128個客戶端
while True: # 回圈為多個客戶端服務
print("waitting connected...")
# 等待電話到來 =》 等待別人電話的到來,此時程式會被阻塞,等待客戶端連接
new_client_socket, client_addr = tcp_socket.accept() # 新的專門為客戶端服務的socket,客戶端的addr
# 接收客戶端發送過來的請求,此時程式會阻塞等待客戶端發送資料
print("waitting recive data...")
while True: # 回圈為同一個客戶端服務多次
recv_data = new_client_socket.recv(BUFSIZE)
# 如果recv 解堵塞,有兩種方式
# 1.客戶端發送過來資料
# 2.客戶端呼叫close斷開連接
if recv_data:
print(f"【{client_addr[0]}:{client_addr[1]}】", recv_data.decode())
# 回送一部分資料給客戶端
new_client_socket.send('收到'.encode())
else:
break
# 關閉套接字
new_client_socket.close()
print("connect closed")
tcp_socket.close()
print('server end...')
監聽套接字負責等待有新的客戶端進行連接
accept產生的新的套接字用來為客戶端服務 如果將監聽套接字關閉了,那么會導致不能再次等待新客戶端的到來,accept()會失敗 關閉accept回傳的新的套接字,意味著不再為這個客戶端服務,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/183064.html
標籤:Python
