zoukankan      html  css  js  c++  java
  • 粘包问题

    TCP遗留问题--粘包

    TCP发送数据的四种情况:

    假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4种情况。

    • 服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包;
    • 服务端一次接收到了两个数据包,D1和D2粘合在一起,被称为TCP粘包;
    • 服务端分两次读取到了两个数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为TCP拆包;
    • 服务端分两次读取到了两个数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余内容D1_2和D2包的整包。

    特例:如果此时服务端TCP接收滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种可能,即服务端分多次才能将D1和D2包接收完全,期间发生多次拆包。

    1. 发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据很小,会合道一起,产生粘包)

      客户端:

      import  socket
      
      client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      
      addr = ('127.0.0.1',8000)
      
      client.connect(addr)
      
      while True:
          # 发送消息
          msg = input("请输入你要讲的话>>>>")
          client.send(bytes(msg.encode('utf8')))
      
          # 接受消息
          leng = client.recv(10)
          print(leng.decode('gbk'))
      

      服务端:

      import  socket
      import subprocess
      
      
      service =  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      
      addr = ('127.0.0.1',8000)
      
      service.bind(addr)
      
      service.listen(5)
      
      conn,addr = service.accept()
      
      while True:
          # 接受消息
          client_msg = conn.recv(1024)
          print(client_msg)
          common = client_msg.decode('utf8')
          print(common)
          obj = subprocess.Popen(common,
                           shell=True,
                           stderr=subprocess.PIPE,
                           stdout = subprocess.PIPE
                           )
          stderr = obj.stderr.read()
          stdout = obj.stdout.read()
          conn.send(stdout+stderr)
      
    2. 接收方不及时接受缓冲区的包,造成多个包接受(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

      客户端:

      # _*_coding:utf-8_*_
      __author__ = 'nickchen121'
      import socket
      BUFSIZE = 1024
      ip_port = ('127.0.0.1', 8080)
      
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      res = s.connect_ex(ip_port)
      
      s.send('hello feng'.encode('utf-8'))
      

      服务端:

      # _*_coding:utf-8_*_
      __author__ = 'nickchen121'
      from socket import *
      ip_port = ('127.0.0.1', 8080)
      
      TCP_socket_server = socket(AF_INET, SOCK_STREAM)
      TCP_socket_server.bind(ip_port)
      TCP_socket_server.listen(5)
      
      conn, addr = TCP_socket_server.accept()
      
      data1 = conn.recv(2)  # 一次没有收完整
      data2 = conn.recv(10)  # 下次收的时候,会先取旧的数据,然后取新的
      
      print('----->', data1.decode('utf-8'))
      print('----->', data2.decode('utf-8'))
      
      conn.close()
      
  • 相关阅读:
    3.15第三周编程总结
    2019.3.9编程总结
    2019.3.3编程总结2
    编程总结1
    编程总结2
    编程总结3
    我的老师
    关于sublime text 3使用记录
    12. 整数转罗马数字
    4. 寻找两个有序数组的中位数
  • 原文地址:https://www.cnblogs.com/plf-Jack/p/11105240.html
Copyright © 2011-2022 走看看