第70天python学习TCP粘包解决方案struct模块

接下来我们先来介绍下可以解决黏包的模块的用法:

struct

python中的struct模块就提供了这样的机制,该模块的主要作用就是对python基本类型值与用python字符串格式表示的C struct类型间的转化(This module performs conversions between Python values and C structs represented as Python strings.)。stuct模块提供了很简单的几个函数,下面写例子。

两个函数:pack()、unpack()

struct模块最重要的两个函数就是pack()unpack()方法

打包函数:pack(fmt, v1, v2, v3, ...)

解包函数:unpack(fmt, buffer)

 服务器:

import struct
# pack 把任意长度的数字转化成固定4个字节长度的字节流
# unpack 将4个字节的值恢复成原本的数据,最后返回一个元组

res = struct.pack("i",2372722) #不能超过int 范围
print(res)
print(len(res))

res = struct.unpack("i",res)
print(res)
print(res[0],type(res[0]))

import struct
import socket

tcp_sever = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#在bind方法之前加上这句话,可以让一个端口重复使用
tcp_sever.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

#绑定地址端口(在网络上注册主机)
tcp_sever.bind(("127.0.0.1", 8080))
tcp_sever.listen(5)

conn,addr = tcp_sever.accept()
inp = input(">>>msg:")
msg = inp.encode("utf-8")

#发送数据的长度通过pack进行替换,变成具有固定长度的4个字节的值
res = struct.pack("i",len(msg))
conn.send(res)
#接下来,开始真正的发送数据
conn.send(msg)
conn.send("world".encode("utf-8"))

res = conn.recv(1024)
print(res)
print(res.decode("utf-8"))

#四次挥手
conn.close()
#退还端口
tcp_sever.close()

客户端:

import socket
import time
import struct
tcp_clint = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_clint.connect(("127.0.0.1", 8080))

time.sleep(0.1)
#接收4个字节长度,它实际要发送的那个数字转化来的
n = tcp_clint.recv(4)
n = struct.unpack("i",n)[0]
print(n)
#接下来接收服务端发送过来的数据
res1 = tcp_clint.recv(n)
print(res1.decode("utf-8"))
res2 = tcp_clint.recv(1024)
print(res2.decode("utf-8"))

#空格不是ascii编码中,大家注意
tcp_clint.send(b'likejjjhkjhjhk')

#关闭连接
tcp_clint.close()

posted on 2019-11-19 21:45  坚持是多么伟大的事情  阅读(217)  评论(0编辑  收藏  举报