python3 使用struct模块解决tcp黏包

时间:2021-10-25 09:37:41
---------------------------------------------struct_server.py-------------------------------------------
# coding:utf-8
import struct
import socket
import subprocess

server = socket.socket()
ip_port = ("127.0.0.1", 8001)
server.bind(ip_port)
server.listen(5)
conn, addr = server.accept()
while 1:
from_client_msg = conn.recv(1024)
print("来自客户端的消息:", from_client_msg.decode("utf-8"))
if not from_client_msg.decode("utf-8"):
print("stop")
break
res = subprocess.Popen(
from_client_msg.decode("utf-8"),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
cmd_result = res.stderr.read()
if not cmd_result:
cmd_result = res.stdout.read()
cmd_result_len = len(cmd_result)
print("一会要发送数据的真实长度:", cmd_result_len)
conn.send(struct.pack('i', cmd_result_len)) # 先发送struct打包后的数据长度
conn.sendall(cmd_result) # 再发送真实数据

conn.close()
server.close()

---------------------------------------------struct_client.py-------------------------------------------

# coding:utf-8
import socket
import struct

client = socket.socket()
ip_port = ("127.0.0.1", 8001)
client.connect(ip_port)

while 1:
cmd = input(">>>: ").strip()
if not cmd:
break
client.send(cmd.encode("utf-8")) # 发送dir或ipconfig命令
from_server_msg = client.recv(4) # 先接收struct打包的后数据长度
from_server_msg_len = struct.unpack('i', from_server_msg) # struct解包
from_server_msg_len = from_server_msg_len[0] # 获取真实数据的长度
print("来自服务端的消息:", from_server_msg, from_server_msg_len)
from_server_real_msg = client.recv(1024) # 再接收真实数据
real_msg_len = len(from_server_real_msg) # 获取第一次获取真实数据的长度
while from_server_msg_len > real_msg_len: # 如果一次没有获取完真实数据
from_server_real_msg += client.recv(1024) # 再次接收真实数据
real_msg_len = len(from_server_real_msg)

print("来自服务端的消息:", from_server_real_msg.decode("gbk"))

client.close()