zoukankan      html  css  js  c++  java
  • 粘包问题及解决方案

    一、粘包问题
    问题1: 无法确认对方发送过来数据的大小。

    ‘client.py'

    import socket

    client = socket.socket()

    client.connect(
    ('127.0.0.1', 9000)
    )

    while True:

    cmd = input('客户端输入的内容: ')

    client.send(cmd.encode('utf-8'))

    data = client.recv(19190)
    print(len(data))
    print(data.decode('gbk'))
    ‘server.py'

    import socket
    import subprocess

    server = socket.socket()
    server.bind(('127.0.0.1',9000))
    server.listen(5)

    while True:
    conn,addr = server.accept()
    print(addr)
    while True:
    try:
    cmd = conn.recv(10)
    if len(cmd) == 0:
    continue
    cmd = cmd.decode('utf-8') #utf8
    if cmd == 'q':
    break
    #调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
    obj = subprocess.Popen(
    #cmd接受的是解码后的字符串
    cmd,shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )
    #结果交给result变量名
    result = obj.stdout.read()+obj.stderr.read()
    print(len(result))
    print(result.decode('gbk')) #windows系统下默认编码gbk
    #将结果返回给客户端
    conn.send(result)

    except Exception as e:
    print(e)
    break
    conn.close()

    问题2: 在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送。

    ‘client.py'

    import socket

    client = socket.socket()

    client.connect(
    ('127.0.0.1', 9000)
    )

    client.send(b'hello')
    client.send(b'hello')
    client.send(b'hello')
    ‘server.py'

    import socket

    server = socket.socket()

    server.bind(
    ('127.0.0.1', 9000)
    )

    server.listen(5)

    conn, addr = server.accept()

    data = conn.recv(5)
    print(data) # b'hello'

    data = conn.recv(1024)
    print(data) # b'hello'

    data = conn.recv(1024)
    print(data) # b'hello'
    二、粘包问题的解决方案:
    粘包问题的解决方案: 确认对方数据的大小。

    这里需要用 struct模块

    struct是什么?
    是一个python内置的模块,它可以将固定长度的数据,打包成固定格式的长度。
    固定格式:如 “ i ” 模式
    i : 4

    struct作用:
    可以将真实数据,做成一个固定长度的报头,客户端发送给服务器,服务器可以接受报头,然后对报头进行解包,获取真实数据的长度,进行接收即可

    import struct

    data = b'1111111111111111'
    print(len(data)) #16

    #打包制作报头
    header = struct.pack('i',len(data))
    print(header) #b'x10x00x00x00'
    print(len(header)) #4

    #解包获取真实数据长度 --->得到一个元组,元组中第一个值是真实数据的长度
    res = struct.unpack('i',header)[0]
    print(res) #16

    无论哪一端先发送数据

    客户端
    - 1) 先制作报头,并发送 (struct)
    - 2) 发送真实数据

    服务端:
    - 1) 接收报头,并解包获取 真实数据长度
    - 2) 根据真实数据长度 接收真实数据
    recv(真实数据长度)

    ‘client.py'

    在这里插入代码片import socket
    import struct

    client = socket.socket()

    client.connect(
    ('127.0.0.1', 9000)
    )

    while True:

    cmd = input('客户端输入的内容: ')
    cmd_bytes = cmd.encode('utf-8')

    #做一个报头
    header = struct.pack('i',len(cmd_bytes))
    print(len(header))
    client.send(header)

    #待服务端确认长度后,发送真实数据长度
    client.send(cmd_bytes)
    #接受服务端的报头
    headers = client.recv(4)

    #解包,接受服务器返回的真实数据的长度
    data_len = struct.unpack('i',headers)[0]
    result = client.recv(data_len)

    print('接受服务器返回的真实数据的长度',len(result))
    print(result.decode('gbk'))

    # 问题2:
    # import socket
    #
    # client = socket.socket()
    #
    # client.connect(
    # ('127.0.0.1', 9000)
    # )
    #
    # client.send(b'hello')
    # client.send(b'hello')
    # client.send(b'hello')

    ‘server.py'

    import socket
    import subprocess
    import struct

    server = socket.socket()
    server.bind(('127.0.0.1',9000))
    server.listen(5)

    while True:
    conn,addr = server.accept()
    print(addr)
    while True:
    try:
    #获取客户端传过来的报头
    header = conn.recv(10)
    #解包获取真实数据的长度
    data_len = struct.unpack('i',header)[0]

    #准备接受真实数据
    cmd = conn.recv(data_len)

    if len(cmd) == 0:
    continue
    cmd = cmd.decode('utf-8') #utf8
    if cmd == 'q':
    break
    #调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
    obj = subprocess.Popen(
    #cmd接受的是解码后的字符串
    cmd,shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )
    #结果交给result变量名
    result = obj.stdout.read()+obj.stderr.read()
    print('发送给服务端返回的真实数据的长度', len(result))
    # print(result.decode('gbk')) #windows系统下默认编码gbk

    # 做一个报头,返回给客户端
    header = struct.pack('i', len(result))
    print(len(header))
    conn.send(header)

    #将结果返回给客户端
    conn.send(result)


    except Exception as e:
    print(e)
    break
    conn.close(
    原文链接:https://blog.csdn.net/weixin_45816565/article/details/103410678

  • 相关阅读:
    odoo国际化翻译
    Odoo创建基础模块和相关内容
    odoo权限管理(二.记录管理)
    推荐的 MongoDB 安装文档
    Python Spider 抓取今日头条街拍美图
    Python Spider 抓取猫眼电影TOP100
    如何选择 SQL Server 数据库跟操作系统版本
    Mongodb 折腾笔记
    MySQLReport
    kernel TCP time wait bucket table overflow
  • 原文地址:https://www.cnblogs.com/zhangjinyi97/p/11991939.html
Copyright © 2011-2022 走看看