粘包问题及解决方案
Posted zhangjinyi97
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了粘包问题及解决方案相关的知识,希望对你有一定的参考价值。
一、粘包问题
问题1: 无法确认对方发送过来数据的大小。
‘client.py‘
import socket
client = socket.socket()
client.connect(
(‘127.0.0.1‘, 9000)
)
while True:
cmd = input(‘客户端输入的内容: ‘)
client.send(cmd.encode(‘utf-8‘))
data = client.recv(19190)
print(len(data))
print(data.decode(‘gbk‘))
‘server.py‘
import socket
import subprocess
server = socket.socket()
server.bind((‘127.0.0.1‘,9000))
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
cmd = conn.recv(10)
if len(cmd) == 0:
continue
cmd = cmd.decode(‘utf-8‘) #utf8
if cmd == ‘q‘:
break
#调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
obj = subprocess.Popen(
#cmd接受的是解码后的字符串
cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
#结果交给result变量名
result = obj.stdout.read()+obj.stderr.read()
print(len(result))
print(result.decode(‘gbk‘)) #windows系统下默认编码gbk
#将结果返回给客户端
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
问题2: 在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送。
‘client.py‘
import socket
client = socket.socket()
client.connect(
(‘127.0.0.1‘, 9000)
)
client.send(b‘hello‘)
client.send(b‘hello‘)
client.send(b‘hello‘)
‘server.py‘
import socket
server = socket.socket()
server.bind(
(‘127.0.0.1‘, 9000)
)
server.listen(5)
conn, addr = server.accept()
data = conn.recv(5)
print(data) # b‘hello‘
data = conn.recv(1024)
print(data) # b‘hello‘
data = conn.recv(1024)
print(data) # b‘hello‘
二、粘包问题的解决方案:
粘包问题的解决方案: 确认对方数据的大小。
这里需要用 struct模块
struct是什么?
是一个python内置的模块,它可以将固定长度的数据,打包成固定格式的长度。
固定格式:如 “ i ” 模式
i : 4
struct作用:
可以将真实数据,做成一个固定长度的报头,客户端发送给服务器,服务器可以接受报头,然后对报头进行解包,获取真实数据的长度,进行接收即可
import struct
data = b‘1111111111111111‘
print(len(data)) #16
#打包制作报头
header = struct.pack(‘i‘,len(data))
print(header) #b‘x10x00x00x00‘
print(len(header)) #4
#解包获取真实数据长度 --->得到一个元组,元组中第一个值是真实数据的长度
res = struct.unpack(‘i‘,header)[0]
print(res) #16
无论哪一端先发送数据
客户端
- 1) 先制作报头,并发送 (struct)
- 2) 发送真实数据
服务端:
- 1) 接收报头,并解包获取 真实数据长度
- 2) 根据真实数据长度 接收真实数据
recv(真实数据长度)
‘client.py‘
在这里插入代码片import socket
import struct
client = socket.socket()
client.connect(
(‘127.0.0.1‘, 9000)
)
while True:
cmd = input(‘客户端输入的内容: ‘)
cmd_bytes = cmd.encode(‘utf-8‘)
#做一个报头
header = struct.pack(‘i‘,len(cmd_bytes))
print(len(header))
client.send(header)
#待服务端确认长度后,发送真实数据长度
client.send(cmd_bytes)
#接受服务端的报头
headers = client.recv(4)
#解包,接受服务器返回的真实数据的长度
data_len = struct.unpack(‘i‘,headers)[0]
result = client.recv(data_len)
print(‘接受服务器返回的真实数据的长度‘,len(result))
print(result.decode(‘gbk‘))
# 问题2:
# import socket
#
# client = socket.socket()
#
# client.connect(
# (‘127.0.0.1‘, 9000)
# )
#
# client.send(b‘hello‘)
# client.send(b‘hello‘)
# client.send(b‘hello‘)
‘server.py‘
import socket
import subprocess
import struct
server = socket.socket()
server.bind((‘127.0.0.1‘,9000))
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
#获取客户端传过来的报头
header = conn.recv(10)
#解包获取真实数据的长度
data_len = struct.unpack(‘i‘,header)[0]
#准备接受真实数据
cmd = conn.recv(data_len)
if len(cmd) == 0:
continue
cmd = cmd.decode(‘utf-8‘) #utf8
if cmd == ‘q‘:
break
#调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
obj = subprocess.Popen(
#cmd接受的是解码后的字符串
cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
#结果交给result变量名
result = obj.stdout.read()+obj.stderr.read()
print(‘发送给服务端返回的真实数据的长度‘, len(result))
# print(result.decode(‘gbk‘)) #windows系统下默认编码gbk
# 做一个报头,返回给客户端
header = struct.pack(‘i‘, len(result))
print(len(header))
conn.send(header)
#将结果返回给客户端
conn.send(result)
except Exception as e:
print(e)
break
conn.close(
原文链接:https://blog.csdn.net/weixin_45816565/article/details/103410678
以上是关于粘包问题及解决方案的主要内容,如果未能解决你的问题,请参考以下文章