当前位置:   article > 正文

服务端网络通信TLV_tlv协议

tlv协议

服务端网络通信TLV

一、TLV协议

TLV协议是通信协议的一种,通讯协议就是指通信双方对数据传送控制的一种约定。 例如常见的TCP/IP、UDP协议等等都是通信协议。但是上述所提到的协议是不可以更改的。但是实际业务处理当中,我们在端对端通信时数据是不固定,所以我们希望可以让我们自定义的通信协议,它可以实现我们自己设定数据发送以及数据的封装形式,再通过上层的网络传输协议发送给对端,对端再根据自己定义好的协议对数据进行解析,从而得到想要的数据。TLV协议便是一种提供用户自定义的通讯协议*

二、TLV解析(三元组编码)

数据的类型Tag(T)2字节 or 4字节
数据的长度Length(L)2字节 or 4字节
数据的值Value(V)由length指定

它规定了一帧数据的前几个字节来表示数据类型,紧接着几个字节表示数据长度,最后是数据的内容。TL 的长度固定,一般是2或4个字节,V 的长度由 Length 指定。

注意:字节序

​ 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。字节序一般分为大端小端。 就是注意一下大小端存储

三、简单实现

1、定义TLV数据类型

//自定义数据类型枚举
namespace TLVType
{
    enum
    {
        TT_CHAR = 0,   // C 8位字符
        TT_SHORT,      // h 16位整型
        TT_INT32,      // i 32位整型
        TT_STRING,     // s 0结尾的字符串
        TT_COUNT,
    };
}

typedef unsigned short TLVType_t;     // tlv 类型
typedef unsigned short TLVLength_t;   // tlv 长度
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2、将数据TLV数据化

// 按format格式,从va_list中提取参数,进行序列化
bool TLVSerializer::Push(TLVType_t type, TLVLength_t length, const void *value)
{
    if (type < TLVType::TT_CHAR || type >= TLVType::TT_COUNT)
    {
        return false;
    }

    if (m_size + (int)length > m_max_size)
    {
        return false;
    }

    //push 类型
    int len = sizeof(TLVType_t);
    memcpy(m_buffer + m_size, &type, len);
    m_size += len;

    //push 长度
    len = sizeof(TLVLength_t);
    memcpy(m_buffer + m_size, &length, len);
    m_size += len;

    //push 数据
    memcpy(m_buffer + m_size, value, length);
    m_size += length;

    return true;
}

bool TLVSerializer::Pushf(const char* format, ...)
{
    va_list v;
    va_start(v, format);
    bool ret = Pushv(format, v);
    va_end(v);
    return ret;
}

bool TLVSerializer::Pushv(const char* format, va_list v)
{
    const char *p = MakeTLV(this, format, v);

    return p != 0;
}

const char* MakeTLV(TLVSerializer* tlv, const char* format, va_list v)
{
    const char* p = format;
    for ( ; *p != 0; p++)
    {
        bool ret = false;
        switch (*p)
        {
        case 'c':
            {
                unsigned char c = va_arg(v, int);
                ret = tlv->Push(TLVType::TT_CHAR, sizeof(char), &c);
            }
            break;
        case 'h':
            {
                short c = va_arg(v, int);
                ret = tlv->Push(TLVType::TT_SHORT, sizeof(short), &c);
            }
            break;
        case 'i':
            {
                int c = va_arg(v, int);
                ret = tlv->Push(TLVType::TT_INT32, sizeof(int), &c);
            }
            break;
        case 's':
            {
                const char *c = va_arg(v, const char*);
                ret = tlv->Push(TLVType::TT_STRING, strlen(c)+1, c);
            }
            break;
        default:
            break;
        }
        if (!ret)
            return 0;
    }

    return p; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

3、将数据TLV反序列化

// 按format格式,进行反序列化,将提取的参数放入va_list中
bool TLVUnserializer::Pop(TLVType_t type, const void *value)
{
    if (type < TLVType::TT_CHAR || type >= TLVType::TT_COUNT)
    {
        return false;
    }

    // pop 类型
    int len = sizeof(TLVType_t);
    TLVType_t pop_type;
    memcpy(&pop_type, m_cur_ptr, len);
    if (pop_type != type)
    {
        return false;
    }
    
    // pop 长度
    m_cur_ptr += len;
    len = sizeof(TLVLength_t);
    TLVLength_t length;
    memcpy(&length, m_cur_ptr, len);
    if (length <= 0 || length >= m_size)
    {
        return false;
    }

    // pop 数据
    m_cur_ptr += len;
    memcpy((char*)value, m_cur_ptr, length);
    m_cur_ptr += length;

    return true;
}

bool TLVUnserializer::Popf(const char* format, ...)
{
   va_list v;
   va_start(v, format);
   bool ret = Popv(format, v);
   va_end(v);
   return ret;
}

bool TLVUnserializer::Popv(const char* format, va_list v)
{
    const char* p = PopTLV(this, format, v);

    return p != 0;
}

const char* PopTLV(TLVUnserializer* tlv, const char* format, va_list v)
{
    const char* p = format;
    for ( ; *p != 0; p++)
    {
        bool ret = false;
        switch(*p)
		{
		case 'c':
            {
                unsigned char *c = va_arg(v, unsigned char*);
                ret = tlv->Pop(TLVType::TT_CHAR, c);
            }
            break;
        case 'h':
            {
                short *c = va_arg(v, short*);
                ret = tlv->Pop(TLVType::TT_SHORT, c);
            }
            break;
        case 'i':
            {
                int *c = va_arg(v, int*);
                ret = tlv->Pop(TLVType::TT_INT32, c);
            }
            break;
        case 's':
            {
                const char **c = va_arg(v, const char**);
                ret = tlv->Pop(TLVType::TT_STRING, c);
            }
            break;
        default:
            break;
        }
        if (!ret)
            return 0;
    }

    return p; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/497317
推荐阅读
相关标签
  

闽ICP备14008679号