zoukankan      html  css  js  c++  java
  • 四、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()
  • 相关阅读:
    shell bash memo
    python performance measure 02
    跨域的几种方法
    表示集合的数据结构:数组(Array),对象(Object),Map和Set
    [H5]range对象的setStart/setEnd方法
    文件上传:input file FileReader
    localStorage,sessionStorage,cookie使用场景和区别
    设置获取cookie,setCookie,getCookie
    js中__proto__, property, prototype, 对象自身属性方法和原型中的属性方法的区别
    使用正则表达式--切分字符串
  • 原文地址:https://www.cnblogs.com/nuochengze/p/13342110.html
Copyright © 2011-2022 走看看