总结:
黏包有两种:
二、黏包的解决方案
1,问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据。
=(,8080=1s.bind(ip_port)s.Listen(5<span >)<span >while<span > True:
conn,addr=<span >s.accept()
<span >print(<span >'<span >客户端<span >'<span >,addr)
<span >while<span > True:
msg=conn.recv(1024<span >)
<span >if <span >not msg:<span >break<span >
res=subprocess.Popen(msg.decode(<span >'<span >utf-8<span >'),shell=<span >True,\
stdin=<span >subprocess.PIPE,\
stderr=<span >subprocess.PIPE,\
stdout=<span >subprocess.PIPE)
err=<span >res.stderr.read()
<span >if<span > err:
ret=<span >err
<span >else<span >:
ret=<span >res.stdout.read()
data_length=<span >len(ret)
conn.send(str(data_length).encode(<span >'<span >utf-8<span >'<span >))
data=conn.recv(1024).decode(<span >'<span >utf-8<span >'<span >)
<span >if data == <span >'<span >recv_ready<span >'<span >:
conn.sendall(ret)
conn.close()
服务端
==s.connect_ex((,8080<span >while<span > True:msg=input(<span >'<span >>>: <span >'<span >).strip()
<span >if len(msg) == 0:<span >continue
<span >if msg == <span >'<span >quit<span >':<span >break<span >
s.send(msg.encode(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">))length</span>=int(s.recv(1024).decode(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">))s.send(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">recv_ready</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span>.encode(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">))send_size</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">0recv_size</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">0data</span>=b<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">''</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">while</span> recv_size <<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000"> length: data</span>+=s.recv(1024<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">) recv_size</span>+=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">len(data)</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">print</span>(data.decode(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">))
客户端
2.使用time模块,在每次send的时候加入一个time.sleep(0.01),这种方法可以有效地隔开两次send,断开系统的优化,此种方法虽然可以解决黏包问题,但是会造成发送数据时间长
=,8090conn,addr =<span > sk.accept()ret1 = conn.recv(12<span >)
<span >print<span >(ret1)
ret2 = conn.recv(12) <span >#
ret3 = conn.recv(12) <span >#
<span >print<span >(ret2)
<span >print<span >(ret3)
conn.close()
sk.close()sk =<span > socket.socket()
sk.connect((<span >'<span >127.0.0.1<span >',8090<span >))
sk.send(b<span >'<span >hello<span >'<span >)
<span >import<span > time
time.sleep(0.01<span >)
sk.send(b<span >'<span >egg<span >'<span >)
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[] =filesizeJson_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 >)<span >while<span > True:conn,addr=<span >phone.accept()
<span >while<span > True:
cmd=conn.recv(1024<span >)
<span >if <span >not cmd:<span >break
<span >print(<span >'<span >cmd: %s<span >' %<span >cmd)
res</span>=subprocess.Popen(cmd.decode(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">),shell</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">True,stdout</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">subprocess.PIPE,stderr</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">subprocess.PIPE) err</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">res.stderr.read() </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">print</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">(err) </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">if</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000"> err: back_msg</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">err </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">else</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">: back_msg</span>=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">res.stdout.read() conn.send(struct.pack(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">i</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span>,len(back_msg))) <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">#</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">先发back_msg的长度</span> conn.sendall(back_msg) <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">#</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">在发真实的<a href="https://www.jb51.cc/tag/neirong/" target="_blank" >内容</a></span>
<span >
conn.close()
msg=input(<span >'<span >>>: <span >'<span >).strip()
<span >if len(msg) == 0:<span >continue
<span >if msg == <span >'<span >quit<span >':<span >break<span >
s.send(msg.encode(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">utf-8</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">))l</span>=s.recv(4<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">)x</span>=struct.unpack(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">i</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">,l)[0]</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">print</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">(type(x),x)</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">#</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000"> print(struct.unpack('I',l))</span>r_s=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">0data</span>=b<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">''</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">while</span> r_s <<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000"> x: r_d</span>=s.recv(1024<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">) data</span>+=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">r_d r_s</span>+=<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000">len(r_d)</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">#</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000"> print(data.decode('utf-8'))</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff">print</span>(data.decode(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">gbk</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000">'</span>)) <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000">#</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000"><a href="https://m.jb51.cc/tag/windows/" target="_blank" >windows</a><a href="https://www.jb51.cc/tag/mo/" target="_blank" >默</a>认gbk编码</span></pre>
总结 以上是内存溢出为你收集整理的黏包问题的成因与解决方案全部内容,希望文章能够帮你解决黏包问题的成因与解决方案所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)