一文詳解Python中socket庫的完整使用教程
一、socket 簡介
Socket 又稱套接字,是應用程序與網(wǎng)絡傳輸層之間的接口,所有網(wǎng)絡通信都基于 Socket。
Python 內(nèi)置 socket 模塊,無需額外安裝,可以直接完成 TCP、UDP 通信。
網(wǎng)絡兩大傳輸協(xié)議:
- TCP(SOCK_STREAM):面向連接、可靠、三次握手,不會丟包。
- UDP(SOCK_DGRAM):無連接、不可靠,直接發(fā)送數(shù)據(jù)包,速度更快。
導入模塊:
import socket
二、socket 對象創(chuàng)建
語法
socket.socket(family, type)
family=socket.AF_INET:IPv4(最常用)type=socket.SOCK_STREAM:TCPtype=socket.SOCK_DGRAM:UDP
示例:
# 創(chuàng)建TCP套接字 tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 創(chuàng)建UDP套接字 udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
第一部分:TCP 通信全套API
TCP通信分為客戶端和服務端。
1. TCP 客戶端常用方法
| 方法 | 作用 |
|---|---|
connect((host, port)) | 和服務端建立TCP連接 |
send(bytes) | 發(fā)送字節(jié)數(shù)據(jù) |
recv(buffer_size) | 接收數(shù)據(jù),返回bytes |
settimeout(n) | 設置阻塞超時時間 |
close() | 關閉套接字 |
完整客戶端代碼
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5) # 5秒無響應則超時
# 建立連接
sock.connect(("127.0.0.1", 8080))
# 發(fā)送數(shù)據(jù),只能發(fā)送bytes
sock.send("你好服務端".encode("utf-8"))
# 接收數(shù)據(jù),最多讀取1024字節(jié)
data = sock.recv(1024)
print(data.decode("utf-8"))
sock.close()
2. TCP 服務端常用方法
| 方法 | 作用 |
|---|---|
bind((ip, port)) | 綁定本機IP與端口 |
listen(n) | 開啟監(jiān)聽,n為等待隊列長度 |
accept() | 阻塞等待客戶端接入,返回(conn, address) |
完整服務端代碼
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 端口復用,避免重啟時報端口被占用
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("0.0.0.0", 8080))
server.listen(5)
print("服務端已啟動,等待連接...")
# 阻塞等待客戶端
conn, client_addr = server.accept()
print("客戶端地址:", client_addr)
# 接收消息
msg = conn.recv(1024)
print("收到:", msg.decode())
# 回復消息
conn.send("收到消息".encode("utf-8"))
# 關閉當前客戶端連接
conn.close()
第二部分:UDP 通信全套API
UDP 不需要建立連接,沒有 connect(可選),核心方法只有兩個:
| 方法 | 作用 |
|---|---|
sendto(data, (ip, port)) | 發(fā)送數(shù)據(jù)并指定目標地址 |
recvfrom(buffer) | 接收數(shù)據(jù),同時獲取發(fā)送方地址 |
1. UDP客戶端(只發(fā)數(shù)據(jù))
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 發(fā)送UDP數(shù)據(jù)包
sock.sendto(b"心跳包", ("127.0.0.1", 9999))
sock.close()
2. UDP服務端接收數(shù)據(jù)
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 9999))
while True:
data, addr = sock.recvfrom(1024)
print(f"來自{addr}: {data.decode()}")
# 回包
sock.sendto(b"ok", addr)
3. UDP廣播設置
局域網(wǎng)設備發(fā)現(xiàn)必備:
# 開啟廣播權限
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(b"online", ("255.255.255.255", 9999))
三、socket 高頻通用配置選項
1. 端口復用(必加)
解決服務端重啟提示 Address already in use
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2. 設置阻塞超時
recv、accept 默認永久阻塞,必須加超時防止程序卡死
sock.settimeout(3)
捕獲異常:
try:
data = sock.recv(1024)
except socket.timeout:
print("接收超時")
3. 關閉Nagle算法,小包立即發(fā)送
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
4. 獲取本機IP
socket.gethostbyname(socket.gethostname())
5. 域名解析為IP
socket.gethostbyname("www.baidu.com")
四、TCP 經(jīng)典問題:粘包問題
TCP是字節(jié)流,沒有數(shù)據(jù)包邊界,多次發(fā)送的數(shù)據(jù)會粘在一起。
解決方案:
- 固定每條消息長度;
- 先發(fā)送數(shù)據(jù)長度,再發(fā)送正文;
- 使用換行符、特殊字符做分隔。
簡單分隔示例:
# 發(fā)送端 sock.send(b"hello|||") # 接收端按分隔符切割數(shù)據(jù)
五、常用實戰(zhàn)小案例
案例1:TCP端口存活檢測
def port_check(host, port, timeout=2):
try:
sock = socket.socket()
sock.settimeout(timeout)
sock.connect((host, port))
sock.close()
return True
except:
return False
案例2:裸Socket發(fā)送HTTP請求(不使用requests)
sock = socket.socket()
sock.connect(("www.baidu.com", 80))
http_header = b"GET / HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:close\r\n\r\n"
sock.send(http_header)
print(sock.recv(4096).decode("utf-8", errors="ignore"))
sock.close()
六、核心方法匯總表
TCP專用
- connect()
- listen()
- bind()
- accept()
- send()
- recv()
UDP專用
- sendto()
- recvfrom()
公共方法
- settimeout()
- setsockopt()
- close()
七、避坑總結(jié)
- 所有收發(fā)數(shù)據(jù)必須是
bytes,字符串必須.encode("utf-8"); - TCP必須先連接再收發(fā),UDP直接發(fā)包;
- recv緩沖區(qū)要合理設置,太小會讀不全數(shù)據(jù);
- 一定要設置超時,避免無限阻塞;
- 服務端綁定
0.0.0.0才能對外網(wǎng)與局域網(wǎng)開放;綁定127.0.0.1僅本機訪問; - 短連接收發(fā)完畢及時close,避免大量TIME_WAIT占用端口。
如果你需要,我可以繼續(xù)寫:
- 多線程TCP服務端
- asyncio異步socket并發(fā)探測
- 自定義TCP分包協(xié)議解決粘包完整版代碼。
到此這篇關于一文詳解Python中socket庫的完整使用教程的文章就介紹到這了,更多相關Python socket庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
TensorFlow實現(xiàn)卷積神經(jīng)網(wǎng)絡
這篇文章主要為大家詳細介紹了TensorFlow實現(xiàn)卷積神經(jīng)網(wǎng)絡,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
python中pandas.DataFrame排除特定行方法示例
這篇文章主要給大家介紹了關于python中pandas.DataFrame排除特定行的方法,文中給出了詳細的示例代碼,相信對大家的理解和學習具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03

