-
-
tcp是流式协议,数据像水流一样粘在一起,没有任何边界区分
-
收数据没收干净
粘包解决思路
-
每次都收干净,不要任何残留
粘包解决办法
-
利用好
struct
模块服务端
-
-
通过struct这个模块,构造固定长度的数据包头信息,接着才发送数据,即自定义的协议
-
代码
import socket
import struct
import subprocess
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 8080))
server.listen(5)
while True:
client, client_addr = server.accept()
while True:
try:
recv_msg = client.recv(1024)
if len(recv_msg) == 0:
break
obj = subprocess.Popen(recv_msg.decode('utf8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_res = obj.stdout.read()
stderr_res = obj.stderr.read()
total_size = len(stdout_res) + len(stderr_res)
# 发送固定长度的header
header = struct.pack('i', total_size)
client.send(header)
# 发送data
client.send(stdout_res)
client.send(stderr_res)
except Exception:
pass
client.close()
客户端
-
先收固定长度的头:解析出数据的描述信息,包括数据的总大小total_size
-
recv_size=0在循环接收data后累加
-
当recv_size=total_size循环接收结束
-
代码
import socket
import struct
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
msg = input("请输入命令>>:").strip()
if len(msg) == 0:
continue
client.send(msg.encode('utf-8'))
# 接受头信息
header = client.recv(4)
total_size = struct.unpack("i", header)[0]
current_size = 0
# 循环接收data
while current_size < total_size:
recv_data = client.recv(1024)
current_size += len(recv_data)
print(recv_data.decode("utf-8"))
else:
print()
-
-