1.struct模块
#1、把整型数字转成bytes类型 #2、转成的bytes是固定长度的 import struct import json header_dic = { ‘total_size‘: 31222222222121, ‘md5‘: ‘123svsaef123sdfasdf‘, ‘filename‘: ‘a.txt‘ } #序列化:内存中的数据结构----》转成一种中间格式(字符串)----》存到文件中 header_json=json.dumps(header_dic) print(header_json,type(header_json)) #编码:编码后的结果为bytes类型 header_bytes=header_json.encode(‘utf-8‘) header_size=len(header_bytes) print(header_size) # 81 #打包 obj=struct.pack(‘i‘,header_size) print(obj,len(obj)) # b‘Q\x00\x00\x00‘ 4 #解包 obj2=struct.unpack(‘i‘,obj) print(obj2) # (81,)
打印结果:
{"total_size": 31222222222121, "md5": "123svsaef123sdfasdf", "filename": "a.txt"} <class ‘str‘> 81 b‘Q\x00\x00\x00‘ 4 (81,)
result
2.通讯整个流程:
‘‘‘ 流程: 服务端:制作报头,把报头信息丢到报头字典里,字典序列化得到json字符串,encode得到bytes ---->发报头长度(struct.pack打成4个bytes)--->发送报头---->发真实数据 客户端:先接收4个bytes:struct.unpack解包报头长度--->接收报头--> 解析报头:decode得到字符串,反序列化得到报头--->根据报头内的信息,收取真实的数据 ‘‘‘
3.具体代码如下:
服务端:
from socket import * import subprocess import struct import json server=socket(AF_INET,SOCK_STREAM) server.bind((‘127.0.0.1‘,8080)) server.listen(5) #监听客户端的链接请求 while True: conn,client_addr=server.accept() #(连接对象,客户端的ip和端口) conn:tcp三次握手的一个产物,可以用来收发消息 print(client_addr) #此处client_addr的作用是可以知道哪个客户端建的链接,和通讯无关 while True: try: cmd=conn.recv(1024) #cmd为bytes类型, obj=subprocess.Popen(cmd.decode(‘utf-8‘), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout=obj.stdout.read() #系统命令,解码需要gbk stderr=obj.stderr.read() # 1、制作报头 header_dic={ ‘total_size‘:len(stdout) + len(stderr), ‘md5‘:‘123svsaef123sdfasdf‘, ‘filename‘:‘a.txt‘ } header_json = json.dumps(header_dic) #json序列化报头 header_bytes = header_json.encode(‘utf-8‘) #字符串类型---->bytes类型,发送 # 2、先发送报头的长度 header_size=len(header_bytes) conn.send(struct.pack(‘i‘,header_size)) # 3、发送报头 conn.send(header_bytes) # 4、发送真实的数据 conn.send(stdout) #send只能发bytes类型 conn.send(stderr) except ConnectionResetError: break conn.close() server.close()
客户端:
from socket import * import struct import json client=socket(AF_INET,SOCK_STREAM) client.connect((‘127.0.0.1‘,8080)) # print(client) while True: cmd=input(‘>>>: ‘).strip() if not cmd:continue client.send(cmd.encode(‘utf-8‘)) #把命令结果发给服务器 #1、先收报头的长度根据报头内的信息,收取真实的数据 header_size=struct.unpack(‘i‘,client.recv(4))[0] #bytes类型,想拿到报头长度要对bytes进行解出 #2、接收报头 header_bytes=client.recv(header_size) #对应服务端的发送报头 #3、解析报头 header_json=header_bytes.decode(‘utf-8‘) #bytes类型---->字符串类型 header_dic=json.loads(header_json) #反序列化拿到报头 print(header_dic) total_size=header_dic[ ‘total_size‘] # print(total_size) #1025 #4、接收数据 recv_size=0 res=b‘‘ while recv_size < total_size: recv_data=client.recv(1024) res+=recv_data recv_size+=len(recv_data) print(res.decode(‘gbk‘)) client.close()
原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/11783058.html
时间: 2024-10-23 22:20:40