粘包处理
客户端粘包:
发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据量很小,TCP优化算法会当做一个包发出去,产生粘包)
服务端粘包
接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
解决方法:(发送一个报头告诉对方我要发的有送多大)
先说下连接循环和通信循环
# 服务端 连接循环+通信循环 import scoket server = socket.socket() server.bind(('127.0.0.1',8686)) # 本地回环地址 server.listen(5) # 半连接池 除了正在服务的 还有五个等待连接 while True: # 连接循环 conn, addr = server.accept() # conn 是双向连接通道 套接字的对象 addr是客户端地址 while True: # 通信循环 try: date = conn.recv(1024) # 等待接收1024字节 ptint(date.decode('utf-8')) if len(date) == 0:break conn.send(date.upper()) # 返回消息 except ConnectResetError as c: #连接中断等待下一个连接诶 print(c) break conn.close() # 客户端 import socket client = socket.socket() client.connect(('127.0.0.1',8686)) while True: cmd = input(">>>").encode('utf-8') client.send(cmd) date = client.recv(1024) print(date)
TCP的粘包问题
# 服务端 import socket server = socket.socket() # 买手机 不传参数默认用的就是TCP协议 server.bind(('127.0.0.1',8080)) # bind((host,port)) 插电话卡 绑定ip和端口 server.listen(5) # 开机 半连接池 conn, addr = server.accept() # 接听电话 等着别人给你打电话 阻塞 data = conn.recv(5) # 听别人说话 接收1024个字节数据 阻塞 print(data) data = conn.recv(5) # 听别人说话 接收1024个字节数据 阻塞 print(data) data = conn.recv(4) # 听别人说话 接收1024个字节数据 阻塞 print(data) # 服务端 import socket client = socket.socket() # 拿电话 client.connect(('127.0.0.1',8080)) # 拨号 写的是对方的ip和port client.send(b'hello') client.send(b'world') client.send(b'baby')
粘包的处理
# 服务端 import socket import subprocess import struct import json server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() while True: try: cmd = conn.recv(1024) if len(cmd) == 0:break cmd = cmd.decode('utf-8') obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) res = obj.stdout.read() + obj.stderr.read() d = {'name':'jason','file_size':len(res),'info':'asdhjkshasdad'} json_d = json.dumps(d) # 1.先制作一个字典的报头 header = struct.pack('i',len(json_d)) # 2.发送字典报头 conn.send(header) # 3.发送字典 conn.send(json_d.encode('utf-8')) # 4.再发真实数据 conn.send(res) # conn.send(obj.stdout.read()) # conn.send(obj.stderr.read()) except ConnectionResetError: break conn.close() # 客户端 import socket import struct import json client = socket.socket() client.connect(('127.0.0.1',8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0:continue client.send(msg) # 1.先接受字典报头 header_dict = client.recv(4) # 2.解析报头 获取字典的长度 dict_size = struct.unpack('i',header_dict)[0] # 解包的时候一定要加上索引0 # 3.接收字典数据 dict_bytes = client.recv(dict_size) dict_json = json.loads(dict_bytes.decode('utf-8')) # 4.从字典中获取信息 print(dict_json) recv_size = 0 real_data = b'' while recv_size < dict_json.get('file_size'): # real_size = 102400 data = client.recv(1024) real_data += data recv_size += len(data) print(real_data.decode('gbk'))