粘包只会出现在tcp,udp传输不会产生粘包现象。解决粘包的原理就是服务器预先向客户端发送客户端即将获取文件的大小。
第一版解决方案:
服务器:
1 # Author : Kelvin 2 # Date : 2019/2/2 17:38 3 from socket import * 4 import subprocess 5 6 ip_conf = ("127.0.0.1", 8888) 7 buffer_capacity = 1024 8 tcp_server = socket(AF_INET, SOCK_STREAM) 9 tcp_server.bind(ip_conf)10 tcp_server.listen(5)11 while True:12 conn, addr = tcp_server.accept()13 while True:14 try:15 cmd = conn.recv(buffer_capacity) # 如果强制断开连接会触发try,try正是解决强制中断连接的问题16 print("收到的cmd:%s" % cmd)17 if not cmd: # 如果使用quit断开连接,服务器会死循环收到空,该判断正是解决此问题18 break19 res = subprocess.Popen(cmd.decode("utf8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,20 stderr=subprocess.PIPE)21 err = res.stderr.read()22 if err:23 back_msg = err24 else:25 back_msg = res.stdout.read()26 if not back_msg:27 back_msg = "acute successful!".encode("gbk")28 length = len(back_msg)29 conn.send(str(length).encode("gbk"))30 re_ready = conn.recv(buffer_capacity).decode("utf8")31 if re_ready == "ready":32 conn.send(back_msg)33 except Exception as e:34 print(e)35 break36 tcp_server.close()
客户端:
1 # Author : Kelvin 2 # Date : 2019/2/2 17:38 3 from socket import * 4 5 ip_conf = ("127.0.0.1", 8888) 6 buffer_capacity = 1024 7 tcp_client = socket(AF_INET, SOCK_STREAM) 8 tcp_client.connect(ip_conf) 9 while True:10 cmd = input("Please input cmd : ")11 if not cmd:12 continue13 if cmd == "quit":14 break15 tcp_client.send(cmd.encode("utf8"))16 re_size = int(tcp_client.recv(buffer_capacity).decode("utf-8"))17 print("大小:", re_size)18 tcp_client.send("ready".encode("utf8"))19 recved_size = 020 recved_data = b""21 while recved_size < re_size:22 recved_data += tcp_client.recv(buffer_capacity)23 recved_size = len(recved_data)24 back_msg = recved_data.decode("gbk")25 print(back_msg)26 tcp_client.close()
升级版:
服务器:
1 # Author : Kelvin 2 # Date : 2019/2/2 17:38 3 from socket import * 4 import subprocess 5 import struct 6 7 ip_conf = ("127.0.0.1", 8888) 8 buffer_capacity = 1024 9 tcp_server = socket(AF_INET, SOCK_STREAM)10 tcp_server.bind(ip_conf)11 tcp_server.listen(5)12 while True:13 conn, addr = tcp_server.accept()14 while True:15 try:16 cmd = conn.recv(buffer_capacity) # 如果强制断开连接会触发try,try正是解决强制中断连接的问题17 print("收到的cmd:%s" % cmd)18 if not cmd: # 如果使用quit断开连接,服务器会死循环收到空,该判断正是解决此问题19 break20 res = subprocess.Popen(cmd.decode("utf8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,21 stderr=subprocess.PIPE)22 err = res.stderr.read()23 if err:24 back_msg = err25 else:26 back_msg = res.stdout.read()27 if not back_msg:28 back_msg = "acute successful!".encode("gbk")29 length = len(back_msg)30 re_length = struct.pack("i", length)31 conn.send(re_length)32 conn.send(back_msg)33 except Exception as e:34 print(e)35 break36 tcp_server.close()
客户端:
1 # Author : Kelvin 2 # Date : 2019/2/2 17:38 3 from socket import * 4 import struct 5 ip_conf = ("127.0.0.1", 8888) 6 buffer_capacity = 1024 7 tcp_client = socket(AF_INET, SOCK_STREAM) 8 tcp_client.connect(ip_conf) 9 while True:10 cmd = input("Please input cmd : ")11 if not cmd:12 continue13 if cmd == "quit":14 break15 tcp_client.send(cmd.encode("utf8"))16 re_size = struct.unpack("i",tcp_client.recv(4))[0]17 print("大小:", re_size)18 recved_size = 019 recved_data = b""20 while recved_size < re_size:21 recved_data += tcp_client.recv(buffer_capacity)22 recved_size = len(recved_data)23 back_msg = recved_data.decode("gbk")24 print(back_msg)25 tcp_client.close()