• socket沾包问题


    为什么会沾包

    1. 发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
    2. 接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包) 

    注意:只有TCP有粘包现象,UDP永远不会粘包

    自制报头解决沾包

    服务端
    1. 把真实数据转换成bytes -->header_bytes
    2. 使用struct.pack('i',len(header_bytes)),生成一个固定长度的报头(4字节的bytes)
    3. 使用sendall(报头+ 真实数据的bytes) 返回数据给客户端
     
    客户端
      1. 客户端先recv(4),接收报头信息
      2. 然后使用struct.unpach('i',报头)解包,获取真实数据的长度
      3. 使用recv(数据长度)接收数据
    import json
    import struct
    from socket import *
    s=socket(AF_INET,SOCK_STREAM)
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(('127.0.0.1',8081))
    s.listen(5)
    while True:
        print('等待链接...')
        conn,addr=s.accept()
        while True:
            try:
                data=conn.recv(1024)
                dic = {'file':'hanqian','size':12345,'md5':'abcdefg'}
                dic_bytes = json.dumps(dic).encode('utf-8')  # 字符串编码后是bytes类型
                h_len = struct.pack('i',len(dic_bytes))  # h_len=4  报头固定长度
                print('报头:',h_len)
                conn.send(h_len+dic_bytes)  # 给客户端返回数据,对端会先接收4个字节获取报头,然后使用struct.unpack('i',报头)解包获取真实数据长度,然后调用s。recv
            except ConnectionResetError as e:
                break
        conn.close()  # 关闭链接
    s.close()  # 关闭监听端口
    服务端-解决沾包
    import struct
    from socket import *
    s=socket(AF_INET,SOCK_STREAM)
    s.connect(('127.0.0.1',8081))
    while True:
        msg=input('输入要发送的数据>>: ').strip()
        if not msg: continue  住
        s.send(msg.encode('utf-8'))  # 发送数据(只能发送字节类型)
        h_val = s.recv(4)  # 先使用4个字节接收报头,获取的是打包后的值(bytes类型)
        print('报头:',h_val)
        data_size = struct.unpack('i',h_val)[0]  # 解使用打包的值解包,data_size=真实数据大小(int类型)
        print('真实数据长度:',data_size)
        data=s.recv(data_size)  # 接受数据
        print(data.decode('gbk'))
    客户端-解决沾包
  • 相关阅读:
    JS一些小算术、1加到50、乘法口诀表、买鸡等
    全选、全不选和反选
    遇重大灾害,缅怀在灾害中遇难的同胞,网站变灰色
    js屏蔽浏览器(IE和FireFox)的刷新和右键等功能
    PHP遍历文件夹下的文件和获取到input name的值
    Glide加载圆角
    android studio的git笔记
    SrollView与RecyclerView
    getIdentifier笔记
    Socket编程基础学习笔记
  • 原文地址:https://www.cnblogs.com/hanqian/p/6508106.html
Copyright © 2020-2023  润新知