黏包问题的成因与解决方案
一、黏包成因tcp协议的拆包机制面向流的通信特点和Nagle算法总结: 黏包有两种:
二、黏包的解决方案1,问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据。
=(,8080=1s.bind(ip_port)
s.listen(5<span style="color: #000000">) <span style="color: #0000ff">while<span style="color: #000000"> True: conn,addr=<span style="color: #000000">s.accept() <span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">客户端<span style="color: #800000">'<span style="color: #000000">,addr) <span style="color: #0000ff">while<span style="color: #000000"> True: msg=conn.recv(1024<span style="color: #000000">) <span style="color: #0000ff">if <span style="color: #0000ff">not msg:<span style="color: #0000ff">break<span style="color: #000000"> res=subprocess.Popen(msg.decode(<span style="color: #800000">'<span style="color: #800000">utf-8<span style="color: #800000">'),shell=<span style="color: #000000">True, stdin=<span style="color: #000000">subprocess.PIPE, stderr=<span style="color: #000000">subprocess.PIPE, stdout=<span style="color: #000000">subprocess.PIPE) err=<span style="color: #000000">res.stderr.read() <span style="color: #0000ff">if<span style="color: #000000"> err: ret=<span style="color: #000000">err <span style="color: #0000ff">else<span style="color: #000000">: ret=<span style="color: #000000">res.stdout.read() data_length=<span style="color: #000000">len(ret) conn.send(str(data_length).encode(<span style="color: #800000">'<span style="color: #800000">utf-8<span style="color: #800000">'<span style="color: #000000">)) data=conn.recv(1024).decode(<span style="color: #800000">'<span style="color: #800000">utf-8<span style="color: #800000">'<span style="color: #000000">) <span style="color: #0000ff">if data == <span style="color: #800000">'<span style="color: #800000">recv_ready<span style="color: #800000">'<span style="color: #000000">: conn.sendall(ret) conn.close() 服务端
==s.connect_ex((,8080<span style="color: #0000ff">while<span style="color: #000000"> True:
msg=input(<span style="color: #800000">'<span style="color: #800000">>>: <span style="color: #800000">'<span style="color: #000000">).strip() <span style="color: #0000ff">if len(msg) == 0:<span style="color: #0000ff">continue <span style="color: #0000ff">if msg == <span style="color: #800000">'<span style="color: #800000">quit<span style="color: #800000">':<span style="color: #0000ff">break<span style="color: #000000">
客户端 2.使用time模块,在每次send的时候加入一个time.sleep(0.01),这种方法可以有效地隔开两次send,断开系统的优化,此种方法虽然可以解决黏包问题,但是会造成发送数据时间长 =,8090conn,addr =<span style="color: #000000"> sk.accept()
ret1 = conn.recv(12<span style="color: #000000">) <span style="color: #0000ff">print<span style="color: #000000">(ret1) ret2 = conn.recv(12) <span style="color: #008000"># ret3 = conn.recv(12) <span style="color: #008000"># <span style="color: #0000ff">print<span style="color: #000000">(ret2) <span style="color: #0000ff">print<span style="color: #000000">(ret3) conn.close() sk.close() sk =<span style="color: #000000"> socket.socket()
sk.connect((<span style="color: #800000">'<span style="color: #800000">127.0.0.1<span style="color: #800000">',8090<span style="color: #000000">)) sk.send(b<span style="color: #800000">'<span style="color: #800000">hello<span style="color: #800000">'<span style="color: #000000">) sk.close()
=socket.socket()
sk.bind((,8080))
sk.listen()
buffer =1024
conn,addr =sk.accept()
head_len=conn.recv(4)
head_len =struct.unpack(,head_len)[0]
json_head =conn.recv(head_len).decode()
head =json.loads(json_head)
filesize =head[]
(filesize)
with open(r%head[],)as f:
filesize:
filesize >=buffer:= buffer值,buffer值是设定的一次接收多少字节的内容
(filesize)
content =conn.recv(buffer)
f.write(content)
filesize -=buffer
:
content ==((
=,8090=1024={:r:r:None}
file_path =os.path.join(head[],head[])
filesize = os.path.getsize(file_path)
head[] =filesize
json_head =json.dumps(head)
bytes_head =json_head.encode()
head_len =len(bytes_head)
pack_len =struct.pack(,head_len)
sk.send(pack_len)
sk.send(bytes_head)
with open(file_path, filesize>==(-===
为什么会出现黏包问题?首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据传输的过程中海油缓存机制来避免数据丢失 因为在连续发送小数据的时候、以及接收大小不符的时候都容易出现黏包现象 本质还是因为我们在接收数据的时候不知道发送的数据的长短 解决黏包问题 在传输大量数据之前先告诉数据量的大小。 4,使用struct解决黏包? =1)
,8080phone.listen(5<span style="color: #000000">)
<span style="color: #0000ff">while<span style="color: #000000"> True:
conn,addr=<span style="color: #000000">phone.accept() <span style="color: #0000ff">while<span style="color: #000000"> True: cmd=conn.recv(1024<span style="color: #000000">) <span style="color: #0000ff">if <span style="color: #0000ff">not cmd:<span style="color: #0000ff">break <span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">cmd: %s<span style="color: #800000">' %<span style="color: #000000">cmd)
<span style="color: #000000">
s=<span style="color: #000000">socket.socket(socket.AF_INET,8080<span style="color: #000000">))
<span style="color: #0000ff">while<span style="color: #000000"> True:
msg=input(<span style="color: #800000">'<span style="color: #800000">>>: <span style="color: #800000">'<span style="color: #000000">).strip() <span style="color: #0000ff">if len(msg) == 0:<span style="color: #0000ff">continue <span style="color: #0000ff">if msg == <span style="color: #800000">'<span style="color: #800000">quit<span style="color: #800000">':<span style="color: #0000ff">break<span style="color: #000000">
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |