struct 模块解决 TCP黏包问题

时间:2022-06-21 10:17:26
首先来看一下产生黏包现象的一段代码:
# server.py 服务端
import socket
​
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
​
conn,addr = sk.accept()
conn.send('hello,'.encode('utf-8'))
conn.send('world'.encode('utf-8'))
conn.recv(1024)
conn.close()
​
sk.close()
# client.py 客户端
import time
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
​
time.sleep(0.1)
print(sk.recv(12))      # 'hello,worl' 'hello,world'
print(sk.recv(10))      # 'd'         '一直等待接收'
sk.send(b'hahaha')
​
sk.close()

 

 
 
上述代码中。客户端连接了服务端后。服务端连续send了两条数据。客户端随后接收。但是第一次接收 sk.recv(12)  就己经把所有的数据取走了。导致 后面的 recv 一直接收不到数据
下面通过 struct 模块来解决黏包问题:
# server.py 服务端
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
​
conn,addr = sk.accept()
​
msg = '你好'.encode('utf-8')*100
int_num = len(msg)
byte_num = struct.pack('i',int_num)      # 通过 struct.pack方法 转换 int_num 变成4个字节的 bytes
conn.send(byte_num)   
conn.send(msg)
conn.send(b'world')
 
 
<wiz_code_mirror>
 
 
 
 
 
import time,struct
import socket
sk = socket.socket()
​
sk.connect(('127.0.0.1',9000))
time.sleep(0.5)
​
num = struct.unpack('i',sk.recv(4))           # 接收并用 struct.unpack 转换回来 num 是个元祖
print(sk.recv(num[0]).decode('utf-8'))
print(sk.recv(1024))