跳转至

yasio 粘包处理

yasio的粘包处理不仅针对TCP,对于UDP,如果发送端有组包发送机制,也是以相同的方式处理。整体来讲有两种方式:

注意

自定义解码包长度函数实现时,当从字节流中读取int值时,一定不要使用指针强转,否则可能触发ARM芯片字节对齐问题 SIGBUS 异常闪退。可以参考内置解码包长度函数实现 io_channel::__builtin_decode_len

YOPT_C_UNPACK_PARAMS

设置信道拆包参数。

参数

max_frame_length
最大包长度,超过将视为异常包。

length_field_offset
包长度字段相对于消息包数据首字节偏移。

length_field_length
包长度字段大小,支持1~4字节整数(uint8_t,uint16_t,uint24_t,int32_t)。

length_adjustment
包长度调整值。通常应用层二进制协议都会设计消息头和消息体,当长度字段值包含消息头时,则此值为 0,否则为 消息头长度

注意

消息包长度字段必须使用网络字节序编码。请查看内置解码包长度实现:

int io_channel::__builtin_decode_len(void* d, int n)
{
  int loffset = uparams_.length_field_offset;
  int lsize   = uparams_.length_field_length;
  if (loffset >= 0)
  {
    int len = 0;
    if (n >= (loffset + lsize))
    {
      ::memcpy(&len, (uint8_t*)d + loffset, lsize);
      len = yasio::network_to_host(len, lsize);
      len += uparams_.length_adjustment;
      if (len > uparams_.max_frame_length)
        len = -1;
    }
    return len;
  }
  return n;
}

decode_len_fn_t

信道解码消息包长度函数原型。

typedef std::function<int(void* d, int n)> decode_len_fn_t;

参数

d
待解包数据首字节地址。

n
待解包数据长度。

返回值

返回消息包数据实际长度。

  • > 0: 解码包长度成功。
  • == 0: 接收数据不足以解码消息包实际长度,yasio底层会继续接收数据,一旦收到新数据,会再次调用此函数。
  • < 0: 解码包长度异常,会触发当前传输会话断开。

注意

解码消息包长度函数必须是线程安全的,例如对于Lua则不支持设置自定义解码消息包长度函数。