struct模块解决黏包问题
server:
''' 远程执行cmd命令程序 如果不使用struct模块,ipconfig等会返回长数据的命令会发生黏包现象 ''' import socket import struct sk = socket.socket() sk.bind(("127.0.0.1", 8080)) sk.listen() conn, addr = sk.accept() while True: cmd = input(">>>") if cmd == "q": conn.send(b"q") break conn.send(bytes(cmd,encoding="gbk")) # windows系统的命令行的编码格式是GBK所以要进行GBK转码 num = conn.recv(4) # 接收返回数据的长度 num = int(struct.unpack("i",num)[0]) # 将接收的bytes类型的struct转换的数字解码,因为返回的是元组所以取元组的第一个,并且下面要用的类型是整数型,转换成int类型 print(conn.recv(num).decode("gbk")) # 接收上面传进来大小的数据,解码gbk,打印 # 发送多少接收多少就不会产生黏包现象了 conn.close() sk.close()
client:
import socket import struct import subprocess sk = socket.socket() sk.connect(("127.0.0.1", 8080)) while True: cmd = sk.recv(1024).decode("gbk") # Windows命令行是gbk编码,使用gbk解码 if cmd == "q": break res = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 使用subprocess模块执行cmd命令 # 第一个参数是要执行的命令 # shell=True 表示执行的是系统shell命令 # stdout 执行成功输出信息,保存到管道 # stderr 执行失败输出信息,保存到管道 stdout = res.stdout.read() # 读取执行成功信息 stderr = res.stderr.read() # 读取执行失败信息 str_len = len(stdout)+len(stderr) # 取执行成功和失败信息的长度和 num = struct.pack("i",str_len) # 使用struct进行数字固定长度编码 # “i” 表示进行转换的是int类型 -> 转换完成后会是固定4字节的bytes类型 # 第二个参数是长度数字 sk.send(num) # 将长度发送 sk.send(stdout) # 发送执行成功信息 sk.send(stderr) # 发送执行失败信息 sk.close()