#struct模块可以把一个数据类型,例如数字int,转化成固定长度(4个字节)的bytes。int转为4个bytes。
#在大量传输数据之前先告诉接收端即将接收数据的大小,方可解决黏包问题:
#利用struct模块打包要发送的数据的长度,接收端接收这个包,解包之后,接收这个长度的数据。
import struct
pack = struct.pack('i',4096) #打包,'i'代表int,把数字转化成固定长度(4个字节)的bytes。
print(pack) #b'\x00\x10\x00\x00',4个字节(bytes)
unpack = struct.unpack('i',pack)#解包
print(unpack) #(4096,) 解包的结果是一个元祖
print(unpack[0]) #4096,元祖的第一个元素就是字节数
#server:
import socket
import struct
sk = socket.socket()
sk.bind(('127.0.0.1',8888))
sk.listen()
conn,addr = sk.accept()
while True:
cmd = input('>>>')
if cmd == 'q':
conn.send(b'q')
break
conn.send(cmd.encode('gbk')) #encode编码,把str转化为bytes。
pack = conn.recv(4) #接收的是client的包,由4个字节组成,这里不需要decode解码,因为下面是解包。
unpack = struct.unpack('i',pack)
ret = conn.recv(unpack[0]).decode('gbk')
print(ret)
conn.close()
sk.close()
#client:
import socket
import subprocess
import struct
sk = socket.socket()
sk.connect(('127.0.0.1',8888))
while True:
cmd = sk.recv(1024).decode('gbk')
if cmd == 'q':
break
ret = subprocess.Popen(cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
std_out = ret.stdout.read() #读取出来的内容是 bytes
std_err = ret.stderr.read() #读取出来的内容是 bytes
len_num = len(std_out) + len(std_err) #计算出两个输出的长度
pack = struct.pack('i',len_num) #打包长度,pack由4个字节组成
sk.send(pack) #server的pack = conn.recv(4)接收这个pack。
sk.send(std_out)
sk.send(std_err)
sk.close()