socket+循环通信+粘包
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
服务端
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_address = server.accept() print(client_address) while True: try: # 接受数据 cmd = conn.recv(1024) if len(cmd) == 0: break obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout = obj.stdout.read() stderr = obj.stderr.read() # 创建报头 header_dic = { "filename": "a.txt", "md5": "jgfjfgsga1972392lsdj", "total_size": len(stdout) + len(stderr) } # 序列化报头 header_json = json.dumps(header_dic) # 将报头转化成bytes格式 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) 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)) while True: cmd = input(">>:").strip() if len(cmd) == 0: continue # 向服务器发送数据 client.send(cmd.encode("utf-8")) # 获取报头长度 header_size = struct.unpack("i", client.recv(4))[0] # 获取报头 header_bytes = client.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"] # 获取数据 cmd_res = b"" recv_size = 0 while recv_size < total_size: data = client.recv(1024) recv_size += len(data) cmd_res += data print(cmd_res.decode('gbk')) client.close()