python 网络编程-03 粘包问题及处理
粘包问题出现在TCP连接下。
由于client 端通过 tcp 连接 向 server端发送消息,多条消息之间没有明显的区分,导致server端在接收时,会将前一条消息的 结尾与下一天消息的开头放入一个缓冲区进行接收。
导致两条数据粘在一起, 称为粘包。
解决粘包的思路为,在发送一条消息时 将前4个字符设置为消息的长度,让接收端知道消息的长度即可区分不同的消息。
粘包问题及解决 / pro.py
import struct
def sender(conn, msg: bytes):
# 计算消息的长度
pack_head = struct.pack('i', len(msg))
# 发送消息的长度
conn.send(pack_head)
# 发送消息
conn.send(msg)
def receiver(conn) -> str:
# 获取消息的长度
length = struct.unpack('i', conn.recv(4))[0]
print(length)
# 设置缓冲区大小为1024
buff_size = 1024
msg = ''
while True:
if length < buff_size:
# 消息长度小于缓冲区大小 接收数据结束循环
recv_msg = conn.recv(length)
msg += recv_msg.decode('utf-8')
break
else:
# 消息长度大于缓冲区大小
# 接收缓冲区大小的数据
# 数据长度减去已经接收的长度
recv_msg = conn.recv(length)
length -= buff_size
msg = recv_msg.decode('utf-8')
return msg
server.py
import socket, subprocess,traceback
from 粘包问题及解决 import proto
if __name__ == '__main__':
s = socket.socket()
s.bind(('127.0.0.1', 8000))
s.listen()
while True:
print('等待连接')
conn, addr = s.accept()
while True:
try:
commend = proto.receiver(conn)
except Exception as e:
print('连接异常')
conn.close()
print(traceback.print_exc())
break
if commend == 'exit':
conn.close()
break
obj = subprocess.Popen(commend, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out = obj.stdout.read()
err = obj.stderr.read()
if err:
print("err:", err)
proto.sender(conn, err)
else:
print("out", out)
proto.sender(conn, out)
client.py
import socket
from 粘包问题及解决 import proto
if __name__ == '__main__':
s = socket.socket()
s.connect(('127.0.0.1', 8000))
while True:
cmd = input("> ")
proto.sender(s, cmd.encode('utf-8'))
if cmd == 'exit':
s.close()
break
print(proto.receiver(s))