32黏包的解决方式struct模块

Posted wyx666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了32黏包的解决方式struct模块相关的知识,希望对你有一定的参考价值。

黏包的解决方式

  黏包出现的根本原因是接收方不知道要传过来多少数据,解决方法1:在传给接收方以前告诉它要传过去多少数据。  解决方法2:使用struct方法

解决方法1:传之前告诉它要传多少

#服务器端
import socket
sk = socket.socket()
sk.bind((127.0.0.1,8080))
sk.listen()
conn,addr = sk.accept()
while True:
    cmd = input(>>>)
    if cmd == q:
        conn.send(bq)
        break
    conn.send(cmd.encode(gbk))
    num = conn.recv(1024).decode(utf-8)  # 2048
    conn.send(bok)
    res = conn.recv(int(num)).decode(gbk)
    print(res)
conn.close()
sk.close()
#客户端
import socket
import subprocess

sk = socket.socket()
sk.connect((127.0.0.1,8080))
while True:
    cmd = sk.recv(1024).decode(gbk)
    if cmd == q:
        break
    res = subprocess.Popen(cmd,shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    std_out = res.stdout.read()
    std_err = res.stderr.read()
    sk.send(str(len(std_out)+len(std_err)).encode(utf-8))   #2000
    sk.recv(1024)   # ok
    sk.send(std_out)
    sk.send(std_err)
sk.close()

这种方法的好处:确定了我要接收多大的值

  1)要在文件中配置一个配置项:就是每一次recv的大小

  2)当我们要发送大数据的时候,要明确的告诉接收方要发送多大的数据,以便接收方能够准确接收所有的数据。

  3)用处:多用在文件传输的过程中

    1、大文件的传输一定是按照字节读,每一次读固定的字节

    2、传输的过程中,一边读一边传,接收端一边收一边写

    3、send这个大文件之前,每一次文件总量减去固定值

    4、recv这个大文件,每一次接收之后减去固定值

这种方法的不好的地方:多了一次交互

  1)send\sendto,在超过一定范围的时候就会报错

  2)程序的内存管理(啥意思???

 

解决方法二:用struct将文件大小或者长度转化成4个字节的bytes类型

import socket
import subprocess
import struct   #接收命令
sk=socket.socket()
sk.connect((127.0.0.1,8008))
while True:
    cmd=sk.recv(1024).decode(gbk)
    ret=subprocess.Popen(cmd,shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    std_out=ret.stdout.read()
    std_err=ret.stderr.read()
    len_std=len(st_out)+len(std_err)
    len_num=struct.pack(i,len_std)  #将执行命令后的内容长度转化成4个字节类型
    sk.send(len_num)
    sk.send(std_out)
    sk.send(std_err)

sk.close()
#客户端
import socket
import struct
sk=socket.socket()
sk.bind((127.0.0.1,8008))
sk.listen()
con,addr=sk.accept()
while True:
    cmd=input(>>>)
    con.send(cmd.encode(gbk))
    num=con.recv(4)
    len_by=struct.unpack(i,num)[0]  #接收到的4个字节长度转化成数字,重点!!!
    ret=con.recv(len_by).decode(gbk)
    print(ret)
con.close()
sk.close()

 

以上是关于32黏包的解决方式struct模块的主要内容,如果未能解决你的问题,请参考以下文章

使用struct模块解决黏包问题

struct模块解决黏包问题

网络编程- 解决黏包现象方案二之struct模块

struct模块

黏包以及解决

黏包解决方案