四、tcp中的粘包问题解决

  • 粘包问题

    • tcp是流式协议,数据像水流一样粘在一起,没有任何边界区分

    • 收数据没收干净

    粘包解决思路

    • 每次都收干净,不要任何残留

    粘包解决办法

    • 利用好struct模块

      服务端

      • 通过struct这个模块,构造固定长度的数据包头信息,接着才发送数据,即自定义的协议

      • 代码

        import socket
        import struct
        import subprocess

        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind(("127.0.0.1", 8080))
        server.listen(5)

        while True:
           client, client_addr = server.accept()
           while True:
               try:
                   recv_msg = client.recv(1024)
                   if len(recv_msg) == 0:
                       break
                   obj = subprocess.Popen(recv_msg.decode('utf8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                   stdout_res = obj.stdout.read()
                   stderr_res = obj.stderr.read()
                   total_size = len(stdout_res) + len(stderr_res)
                   # 发送固定长度的header
                   header = struct.pack('i', total_size)
                   client.send(header)
                   # 发送data
                   client.send(stdout_res)
                   client.send(stderr_res)
               except Exception:
                   pass
           client.close()

      客户端

      • 先收固定长度的头:解析出数据的描述信息,包括数据的总大小total_size

      • recv_size=0在循环接收data后累加

      • 当recv_size=total_size循环接收结束

      • 代码

        import socket
        import struct

        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

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

        while True:
           msg = input("请输入命令>>:").strip()
           if len(msg) == 0:
               continue
           client.send(msg.encode('utf-8'))
           # 接受头信息
           header = client.recv(4)
           total_size = struct.unpack("i", header)[0]
           current_size = 0
           # 循环接收data
           while current_size < total_size:
               recv_data = client.recv(1024)
               current_size += len(recv_data)
               print(recv_data.decode("utf-8"))
           else:
               print()
posted @ 2020-07-19 23:50  Norni  阅读(208)  评论(0)    收藏  举报