zoukankan      html  css  js  c++  java
  • python 网络编程-03 粘包问题及处理

    粘包问题出现在TCP连接下。
    由于client 端通过 tcp 连接 向 server端发送消息,多条消息之间没有明显的区分,导致server端在接收时,会将前一条消息的 结尾与下一天消息的开头放入一个缓冲区进行接收。
    导致两条数据粘在一起, 称为粘包。

    解决粘包的思路为,在发送一条消息时 将前4个字符设置为消息的长度,让接收端知道消息的长度即可区分不同的消息。

    粘包问题及解决 / pro.py

    import struct
    
    
    def sender(conn, msg: bytes):
        # 计算消息的长度
        pack_head = struct.pack('i', len(msg))
        # 发送消息的长度
        conn.send(pack_head)
        # 发送消息
        conn.send(msg)
    
    
    def receiver(conn) -> str:
        # 获取消息的长度
        length = struct.unpack('i', conn.recv(4))[0]
        print(length)
        # 设置缓冲区大小为1024
        buff_size = 1024
        msg = ''
        while True:
            if length < buff_size:
                #  消息长度小于缓冲区大小  接收数据结束循环
                recv_msg = conn.recv(length)
                msg += recv_msg.decode('utf-8')
                break
            else:
                # 消息长度大于缓冲区大小  
                # 接收缓冲区大小的数据
                # 数据长度减去已经接收的长度
                recv_msg = conn.recv(length)
                length -= buff_size
                msg = recv_msg.decode('utf-8')
    
        return msg
    
    

    server.py

    import socket, subprocess,traceback
    from 粘包问题及解决 import proto
    
    if __name__ == '__main__':
        s = socket.socket()
        s.bind(('127.0.0.1', 8000))
        s.listen()
        while True:
            print('等待连接')
            conn, addr = s.accept()
            while True:
                try:
                    commend = proto.receiver(conn)
                except Exception as e:
                    print('连接异常')
                    conn.close()
                    print(traceback.print_exc())
                    break
                if commend == 'exit':
                    conn.close()
                    break
                obj = subprocess.Popen(commend, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                out = obj.stdout.read()
                err = obj.stderr.read()
                if err:
                    print("err:", err)
                    proto.sender(conn, err)
                else:
                    print("out", out)
                    proto.sender(conn, out)
    

    client.py

    import socket
    from 粘包问题及解决 import proto
    
    if __name__ == '__main__':
        s = socket.socket()
        s.connect(('127.0.0.1', 8000))
        while True:
            cmd = input("> ")
            proto.sender(s, cmd.encode('utf-8'))
            if cmd == 'exit':
                s.close()
                break
            print(proto.receiver(s))
    
    
  • 相关阅读:
    【二十五】cookie与session学习总结
    【二十四】使用mysqli扩展类批量执行多条sql语句
    【二十三】php之预定义超全局变量
    【二十二】mysqli事务处理与预处理总结
    【二十一】基于mysqli的表格数据练习
    【二十】mysqli基于面向过程与面向对象的编程
    为什么所有浏览器的userAgent都带Mozilla
    如何快速的搜索自己想要的资料
    从汇编看c++成员函数指针(三)
    从汇编看c++中指向成员变量的指针(二)
  • 原文地址:https://www.cnblogs.com/pythonPath/p/12402021.html
Copyright © 2011-2022 走看看