粘包的产生原理 以及如何解决粘包问题

内容回顾:
如何与另外一台电脑连接:
ping 对方的ip地址
如何参电脑的ip配置
cmd-->ipconfig

内容概览:
粘包问题
粘包产生原理
如何解决粘包问题


粘包的产生:

#server
import  socket
sk = socket.socket()
ip_port = ('127.0.0.1',8989)
sk.bind(ip_port)
sk.listen()
conn,addr = sk.accept()
conn.send(b'hello,')
conn.send(b'world')
conn.close()
sk.close()

  



#client
import socket
sk = socket.socket()
ip_port = ('127.0.0.1',8989)
sk.connect(ip_port)
ret1 = sk.recv(2)
print(ret1)
ret2 = sk.recv(1024)
print(ret2)
sk.close()

  



#client端收到的结果
b'he'
b'llo,'

  



什么是粘包?
数据之间没有分界线,导致两个数据粘合在一起,被接收端接收的现象,就叫做粘包
-------------插入图片————————
粘包产生的原因:
发送端将两个挨得很近的数据,发送出去,在本地的缓存区粘合在一起,传输给对方,
对方接收到数据之后,由于数据没有界限,于是将两个粘合在一起的数据一起接收。
合包现象:
数据很短
时间间隔很近

拆包现象:
大数据在传输的过程中会发生拆包现象
不会一次性的将数据全部发送给对方
对方接收的时候很可能没有办法一次性接收所有的信息
对方一次没有接收完的信息,会与后面的信息粘在一起

粘包现象只会发生在TCP协议
TCP的协议是流式传输
每一条信息与信息之间是没有界限的

UDP协议中是不会发生粘包的
UDP协议适合短数据的发送
不建议发送过程的信息
数据越长,传输逇过程中,会越容易丢失

解决粘包问题的初探:
能否在发送信息的时候把信息的长度一起发送,接收方根据长度来截取信息。

#server
import  socket
sk = socket.socket()
ip_port = ('127.0.0.1',8989)
sk.bind(ip_port)
sk.listen()

conn,addr = sk.accept()
conn.send(b'0011hello,zhuge')
conn.send(b'0005world')

conn.close()
sk.close()

  



#client
import socket
sk = socket.socket()
ip_port = ('127.0.0.1',8989)
sk.connect(ip_port)

ret1 = sk.recv(4)
len1 = int(ret1.decode('utf-8'))
ret2 = sk.recv(len1)
print(ret2.decode('utf-8'))

ret3 = sk.recv(4)
len2 = int(ret3.decode('utf-8'))
ret4 = sk.recv(len2)
print(ret4.decode('utf-8'))

sk.close()

  



#client显示结果:
hello,zhuge
world

  



总结一下:
上面的办法虽然解决了问题但是存在漏洞,要是长度超过9999就不好使了。
有没有一种算法,输入任意长的数字,得到的是一个四位数,
这个四位数,被接收之后,又可以根据算法反推出这个任意长的数是多少,那么问题就解决了。

struck模块

#server端


conn,addr = sk.accept()
while True:
    s = input('>>>').encode('utf-8')
    pack_num = struct.pack('i',len(s))#s的长度转化成一个4位数
    conn.send(pack_num)
    conn.send(s)

conn.close()
sk.close()

  



#client端
import socket
import struct
sk = socket.socket()
ip_port = ('127.0.0.1',8989)
sk.connect(ip_port)

while True:
    pack_num = sk.recv(4)
    num = struct.unpack('i',pack_num)[0]#这里有个坑,得到的是元组,(10,)
    ret = sk.recv(num)
    print(ret.decode('utf-8'))

sk.close()

  




原文地址:https://www.cnblogs.com/cavalier-chen/p/9649078.html