粘包处理
客户端粘包:
发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据量很小,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'))