swoole tcp数据包边界问题

2022-01-29

因为TCP通信是流式的,在接收1个大数据包时,可能会被拆分成多个数据包发送。多次Send底层也可能会合并成一次进行发送。这里就需要2个操作来解决

  1. 分包:Server收到了多个数据包,需要拆分数据包
  2. 合包:Server收到的数据只是包的一部分,需要缓存数据,合并成完整的包

swoole内置通讯协议

可自动解决这些协议的服务器的TCP数据包边界问题

  1. open_http_protocol
  2. open_http2_protocol
  3. open_websocket_protocol
  4. open_mqtt_protocol

swoole自定义网络协议

  1. EOF结束符协议
    1. 每个数据包结尾加一串特殊字符表示包已结束,如Memcache、FTP、SMTP都使用\r\n作为结束符
    2. 配置1:性能会比较差,Swoole会遍历每个字节
      $server->set(array(
          'open_eof_split' => true,
          'package_eof' => "\r\n",
      ));
      $client->set(array(
          'open_eof_split' => true,
          'package_eof' => "\r\n",
      ));
    3. 配置2:性能会好很多,不用遍历数据,但是只能解决分包问题,没法解决合包问题
      $server->set(array(
          'open_eof_check' => true,
          'package_eof' => "\r\n",
      ));
      $client->set(array(
          'open_eof_check' => true,
          'package_eof' => "\r\n",
      ));
  2. 固定包头 + 包体协议
    1. 这种协议的特点是一个数据包总是由包头+包体2部分组成。包头由一个字段指定了包体或整个包的长度,长度一般是使用2字节/4字节整数来表示。服务器收到包头后,可以根据长度值来精确控制需要再接收多少数据就是完整的数据包
    2. 配置
      $server->set(array(
      	'open_length_check' => true,
      	'package_max_length' => 81920,
      	'package_length_type' => 'n', //see php pack()
      	'package_length_offset' => 0,
      	'package_body_offset' => 2,
      ));

       

{/if}