PYTHON-TCP 粘包

1.TCP的模板代码
收发消息的循环 通讯循环
不断的连接客户端循环 连接循环
判断 用于判断客户端异常退出(抛异常)或close(死循环)

半连接池backlog listen(5)
占用的是内存空间 listen监听请求限制的是请求数 不是链接数
什么情况下会进入半连接池:来不及处理accept 或者客户端单方面终止连接
半连接池的工作原理
目前我们的程序是单线程 服务器要么处理通讯要么处理连接请求 无法同时进行
1 必须绑定规定的ip和port
2 必须对外稳定提供服务
3 必须能支持并发

服务端需要遵循的原则:
1. 服务端与客户端都需要有唯一的地址,但是服务端的地址必须固定/绑定
2. 对外一直提供服务,稳定运行
3. 服务端应该支持并发

2.远程CMD
粘包问题
一方发送空数据 导致程序卡死 今后会通过多线程处理


3.粘包问题 TCP:流式协议
引起粘包的TCP特点:
1 数据流没有开头也没有结果,像水流一样
2 TCP协议有一个nagle算法,

解决粘包的方案 自定义报头

1.先用报头传输数据的长度
对于我们远程CMD程序来说 只要先传输长度就能解决粘包的问题
但是如果做得是一个文件上传下载 除了数据的长度 还需要传输文件的名字 md5等等信息
又该如何?
解决方法:
发送方
1.先告诉对方你要发的数据的长度
2.在发送真实数据
接收方
1.先接收数据的长度信息
2.根据长度信息循环获取直到以获取的长度等于总长度

2.自定义复杂报头 完成发送一些额外的信息 例如文件名
1.将要发送的额外数据打包成一个字典作为报头
3.先发送报头的bytes长度(转json字符串 转bytes字节)
4.再发送报头数据
5.最后发送真实数据

#服务端: #客户端:
# 执行命令
# 显示错误信息和正确信息
# 制作一个报头信息 (转json字符串 转bytes字节)
# 发送报头长度 # 先接收报头的长度(int)
# 发送报头 # 接收报头(字节)
# 发送真实数据 # 解析报头 转为json字符串str,再转为字典dic
# 根据报头内的信息,收取真实的数据



涉及模块:
struct
整型转字节,转成的bytes是固定长度的
i 表示int 长度为4字节 q表示long int 长度为8字节
print(len(struct.pack("i",10240)))
字节转整型 得到一个元祖!!!
print(struct.unpack("q",struct.pack("q",10240))[0])
struct.pack('i',整形变量)
struct.unpack('i',字节变量)

服务器端示例:
# 为了方便存取 可以把需要的信息打包为一个字典
dic{
"filename":"仓老师视频教学 如何做炸鸡!",
"md5":"xzxbzxkbsa1212121",
"total_size":2121221
}
# 字典转字符串? json
head_dic = str(dict)
bytes = head_dic.encode("utf-8")
# 先发送这个字典字符串的长度
dic_len = len(head_dic)
#将长度转为了 字节
bytes_len = struct.pack("i",dic_len)
# 发送报头的长度
c.send(bytes_len)

# 发送真实数据
c.send(xxx.mp4.bytes)
TCP能传的只有字节


# 服务端
#执行结果长
p_len=len(stdout)+len(stderr)
# 将报头信息dic转json字符串,编码为字节,字节的长度,用struct固定,发送报头长度
# 发送报头(编码为字节)
# 再发送真实数据stdout ,stderr

# 客户端

# 先接收报头长度 用struct unpack拿到元祖取[0]
# 接收报头
# 解析报头,解码,json反序列化拿到字典,通过字典获取字典中的总长度
# 根据报头信息,收取真实的数据 按1024接受,判断当总长度>0时不断累加总数据和收到的数据长度





posted @ 2018-11-05 20:40  逐梦~前行  阅读(753)  评论(0编辑  收藏  举报