简单版
服务端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import socket import struct import subprocess phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind((‘127.0.0.1‘,8080)) phone.listen(5) print(‘setting...‘) while True: # 链接循环 conn,A = phone.accept() while True: # 通信循环 try: #1.接收数据 data = conn.recv(8096) print(‘客户端数据:‘,data) #2.执行命令,拿到结果 obj = subprocess.Popen(data.decode(‘utf-8‘), shell=True, # shell 可以解析前面的字符串,相当于cmd stdout=subprocess.PIPE, # 正确管道 stderr=subprocess.PIPE) # 错误管道 stdout = obj.stdout.read() #bytes类型 stderr = obj.stderr.read() #3.将结果返回给客户端 #第一步: 制定固定长度的报头 total_size = len(stdout) + len(stderr) header = struct.pack(‘i‘,total_size) #第二步: 把报头发送给客户端 conn.send(header) #第三步: 在发送真实的数据 conn.send(stdout) conn.send(stderr) #分开写的原因,TCP会自动粘包,可以起到优化的作用 except ConnectionResetError: break conn.close phone.close()
客户端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang ‘‘‘ recv不能设置数值特别大的原因: 1.在接收文件的时候可能超过指定数值 2.自己的操作系统的缓存不能无限大,最大也不能超过操作系统的缓存 ‘‘‘ import socket,struct phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect((‘127.0.0.1‘,8080)) while True: #1.发命令 cmd = input(‘>>:‘).strip() if not cmd:continue phone.send(cmd.encode(‘utf-8‘)) #2.拿到命令结果 #第一步: 先收报头 header = phone.recv(4) #第二步: 从报头中解析出对真实数据的描述信息 (数据的长度) tolal_size = struct.unpack(‘i‘,header)[0] #第三步: 接收真实的数据 recv_size=0 recv_data=b‘‘ while recv_size < tolal_size: res = phone.recv(100) recv_data += res recv_size += len(res) print(recv_data.decode(‘gbk‘)) phone.close()
终极版
服务端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import socket import struct import json import subprocess ‘‘‘ 相对于简单版的优化 1.报头信息少 2.struct的i格式有限制 ‘‘‘ phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind((‘127.0.0.1‘,8080)) phone.listen(5) print(‘setting...‘) while True: # 链接循环 conn,A = phone.accept() while True: # 通信循环 try: #1.接收数据 data = conn.recv(8096) print(‘客户端数据:‘,data) #2.执行命令,拿到结果 obj = subprocess.Popen(data.decode(‘utf-8‘), shell=True, # shell 可以解析前面的字符串,相当于cmd stdout=subprocess.PIPE, # 正确管道 stderr=subprocess.PIPE) # 错误管道 stdout = obj.stdout.read() #bytes类型 stderr = obj.stderr.read() #3.将结果返回给客户端 #第一步: 制定固定长度的报头 header_dic={ ‘filename‘:‘a.txt‘, ‘md5‘:‘xxdxxx‘, ‘total_size‘:len(stdout) + len(stderr) } header_json=json.dumps(header_dic) header_bytes = header_json.encode(‘utf-8‘) #第二步:先发报头的长度 conn.send(struct.pack(‘i‘,len(header_bytes))) #第三步:再发报头 conn.send(header_bytes) #第四步: 在发送真实的数据 conn.send(stdout) conn.send(stderr) #分开写的原因,TCP会自动粘包 except ConnectionResetError: break conn.close phone.close()
客户端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang ‘‘‘ recv不能设置数值特别大的原因: 1.在接收文件的时候可能超过指定数值 2.自己的操作系统的缓存不能无限大,最大也不能超过操作系统的缓存 ‘‘‘ import socket import struct import json phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect((‘127.0.0.1‘,8080)) while True: #1.发命令 cmd = input(‘>>:‘).strip() if not cmd:continue phone.send(cmd.encode(‘utf-8‘)) #2.拿到命令结果 #第一步: 先收报头的长度 obj = phone.recv(4) header_size = struct.unpack(‘i‘,obj)[0] #第二步: 再收报头 header_bytes = phone.recv(header_size) #第三步: 从报头中解析出对真实数据的描述信息 header_json = header_bytes.decode(‘utf-8‘) header_dic = json.loads(header_json) print(header_dic) total_size = header_dic[‘total_size‘] #第四步: 接收真实的数据 recv_size=0 recv_data=b‘‘ while recv_size < total_size: res = phone.recv(1024) recv_data += res recv_size += len(res) print(recv_data.decode(‘gbk‘)) phone.close()