编写数据通信协议代码的小技巧

1.有时候我们需要制定协议与其他设备、后台服务器通信,为了代码后期的易维护性,就不用以下这种方式,因为如果没有协议文档对照这里面代码就给人感觉有点魔幻。

char send_data[64]={0};
send_data[0]=0x49;
send_data[1]=0x52;
....
send_data[63]=0x52;

//或者这样,这样子在修改协议代码还好改一点,但脱离了协议,比较难理解这些赋值的实际含义
int index=0;
send_data[index]=0x49;
send_data[index++]=0x52;
index+=2char flag=0x53;
send_data[index]=flag;
....
send_data[index]=0x52;

有时候还需要小端转大端,上传服务器,如果用这种方法赋值,没有协议文档接手这份代码的人就有点疑惑。实际上,上面的方法运行的速度是最快的,但就是不便维护。

 

2.我们可以将协议头、数据、协议尾分开定义,方便后期协议修改,代码作少量改动。

如果协议允许,可以尝试字节对齐,如4字节对齐、8字节对齐,即short byte等都用对齐占4字节,牺牲性能换取代码的易维护性。

这里就用简单的办法实现,较为容易维护代码,但代码比较冗余,实现转换为大端字节通信。

V1:

myprotocol.h

#ifndef _MYPROTOCOL_H_
#define _MYPROTOCOL_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _my_msg_head
{
    char msg_head[2];
    char version[2];
    char msg_num[4];
    char reply_num[4];
    char utc_time[8];
    char data_len[4];
}my_msg_head;
typedef struct _my_msg_data
{
    char role_id[8];
    char move_type[4];
    char distance[4];
    char speed[2];
}my_msg_data;
typedef struct _my_msg_tail
{
    char msg_tail[2];
}my_msg_tail;
//大端字节序列
void set_short_value_b(char* out,short in);//2
void set_int_value_b(char* out,int in);//4
void set_float_value_b(char* out,float in);//4
void set_double_value_b(char* out,double in);//8
void set_long_long_value_b(char* out,long long in);//8
void set_ushort_value_b(char* out,unsigned short in);//2
void set_uint_value_b(char* out,unsigned int in);//4
void set_ulong_long_value_b(char* out,unsigned long long in);//8
int make_frame_data(my_msg_head *,my_msg_data*,my_msg_tail*,char *in,int in_size);
#ifdef __cplusplus
}
#endif
#endif

myprotocol.c

#include <stdio.h>
#include <string.h>
#include "myprotocol.h"
void set_short_value_b(char* out,short in)
{
    out[0]=(char)((in>>8)&0xff);
    out[1]=(char)(in&0xff);
}
void set_int_value_b(char* out,int in)
{
    out[0]=(char)((in>>24)&0xff);
    out[1]=(char)((in>>16)&0xff);
    out[2]=(char)((in>>8)&0xff);
    out[3]=(char)(in&0xff);
}
void set_float_value_b(char* out,float in)
{
    char *p=(char*)(&in);
    for(int i=0;i<4;i++)
    {
        out[i]=p[4-i-1];
    }

}
void set_double_value_b(char* out,double in)
{

    char *p=(char*)(&in);
    for(int i=0;i<8;i++)
    {
        out[i]=p[8-i-1];
    }
}
void set_long_long_value_b(char* out,long long in)
{
    char *p=(char*)(&in);
    for(int i=0;i<8;i++)
    {
        out[i]=p[8-i-1];
    }
}
void set_ushort_value_b(char* out,unsigned short in)
{

    char *p=(char*)(&in);
    for(int i=0;i<2;i++)
    {
        out[i]=p[2-i-1];
    }
}
void set_uint_value_b(char* out,unsigned int in)
{
    char *p=(char*)(&in);
    for(int i=0;i<4;i++)
    {
        out[i]=p[4-i-1];
    }
}

void set_ulong_long_value_b(char* out,unsigned long long in)
{
    char *p=(char*)(&in);
    for(int i=0;i<8;i++)
    {
        out[i]=p[8-i-1];
    }
}
int make_frame_data(my_msg_head *p_head,my_msg_data* p_data,my_msg_tail* p_tail,char *in,int in_size)
{
    int head_len=sizeof(my_msg_head);
    int data_len=sizeof(my_msg_data);
    int tail_len=sizeof(my_msg_tail);
    int total_len=head_len+ data_len+tail_len;
    if(in_size<total_len)
    {
        return -1;
    }
    memcpy(in,p_head,head_len);
    memcpy(in+head_len,p_data,data_len);
    memcpy(in+head_len+data_len,p_tail,tail_len);
    return total_len;
}

main.c

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include "myprotocol.h"
void printData(char *data,int len)
{
    printf("data :\n");
    for(int i=0;i<len;i++)
    {
        printf("%02x ",(unsigned char)data[i]);
        if(i>0&&((i+1)%10==0))
        {
            printf("\n");
        }
    }
    printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
}
unsigned long long getTime_ms()
{
    struct timespec time1 = {0, 0}; 
    clock_gettime(CLOCK_REALTIME, &time1);   
    unsigned long long ret=((unsigned long long)time1.tv_sec)*1000+((unsigned long long)time1.tv_nsec)/1000/1000+8*60*60*1000;
    printData((char *)&ret,8);
    return ret;
}

int main(int argc, char **argv)
{
    char send_data[512]={0};
    my_msg_head m_head;
    my_msg_data m_data;
    my_msg_tail m_tail;
    memset(&m_head,0,sizeof(m_head));
    memset(&m_data,0,sizeof(m_data));
    memset(&m_tail,0,sizeof(m_tail));
    m_head.msg_head[0]=0x05;
    m_head.msg_head[1]=0x49;
    m_head.version[1]=0x01;
    m_head.version[0]=0x00;
    set_int_value_b(m_head.msg_num,0x1002);
    set_int_value_b(m_head.reply_num,0x20001);
    set_ulong_long_value_b(m_head.utc_time,getTime_ms());
    set_int_value_b(m_head.data_len,sizeof(my_msg_data));
    set_ulong_long_value_b(m_data.role_id,0x1234);
    set_uint_value_b(m_data.move_type,(unsigned int)0x56789);
    set_uint_value_b(m_data.distance,0x1234);
    set_ushort_value_b(m_data.speed,0x5678);
    m_tail.msg_tail[0]=0x05;
    m_tail.msg_tail[1]=0x49;
    int send_len=make_frame_data(&m_head,&m_data,&m_tail,send_data,sizeof(send_data));
    printData(send_data,send_len);
    /*
    小端:
        49 05 01 00 02 10 00 00 01 00  
        02 00 b6 04 9f b0 76 01 00 00  
        12 00 00 00 34 12 00 00 00 00 
        00 00 89 67 05 00 34 12 00 00
        78 56 49 05 
    大端:
        05 49 00 01 00 00 10 02 00 02 
        00 01 00 00 01 76 b0 9f 04 b6 
        00 00 00 12 00 00 00 00 00 00 
        12 34 00 05 67 89 00 00 12 34 
        56 78 05 49
    */
}

 

 

V2

加入了字节长度判断,代码更加冗余了

myprotocol.h

#ifndef _MYPROTOCOL_H_
#define _MYPROTOCOL_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _my_msg_head
{
    char msg_head[2];
    char version[2];
    char msg_num[4];
    char reply_num[4];
    char utc_time[8];
    char data_len[4];
}my_msg_head;
typedef struct _my_msg_data
{
    char role_id[8];
    char move_type[4];
    char distance[4];
    char speed[2];
}my_msg_data;
typedef struct _my_msg_tail
{
    char msg_tail[2];
}my_msg_tail;
//大端字节序列
void set_short_value_b(char* out,short in,int len);//2
void set_int_value_b(char* out,int in,int len);//4
void set_float_value_b(char* out,float in,int len);//4
void set_double_value_b(char* out,double in,int len);//8
void set_long_long_value_b(char* out,long long in,int len);//8
void set_ushort_value_b(char* out,unsigned short in,int len);//2
void set_uint_value_b(char* out,unsigned int in,int len);//4
void set_ulong_long_value_b(char* out,unsigned long long in,int len);//8
int make_frame_data(my_msg_head *,my_msg_data*,my_msg_tail*,char *in,int in_size);
#ifdef __cplusplus
}
#endif
#endif

myprotocol.c

#include <stdio.h>
#include <string.h>
#include "myprotocol.h"
void set_short_value_b(char *out, short in, int len)
{
    if (len != sizeof(short))
        return;
    out[0] = (char)((in >> 8) & 0xff);
    out[1] = (char)(in & 0xff);
}
void set_int_value_b(char *out, int in, int len)
{
    if (len != sizeof(int))
        return;
    out[0] = (char)((in >> 24) & 0xff);
    out[1] = (char)((in >> 16) & 0xff);
    out[2] = (char)((in >> 8) & 0xff);
    out[3] = (char)(in & 0xff);
}
void set_float_value_b(char *out, float in, int len)
{
    if (len != sizeof(float))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 4; i++)
    {
        out[i] = p[4 - i - 1];
    }
}
void set_double_value_b(char *out, double in, int len)
{
    if (len != sizeof(double))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 8; i++)
    {
        out[i] = p[8 - i - 1];
    }
}
void set_long_long_value_b(char *out, long long in, int len)
{
    if (len != sizeof(long long))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 8; i++)
    {
        out[i] = p[8 - i - 1];
    }
}
void set_ushort_value_b(char *out, unsigned short in, int len)
{
    if (len != sizeof(unsigned short))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 2; i++)
    {
        out[i] = p[2 - i - 1];
    }
}
void set_uint_value_b(char *out, unsigned int in, int len)
{
    if (len != sizeof(unsigned int))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 4; i++)
    {
        out[i] = p[4 - i - 1];
    }
}

void set_ulong_long_value_b(char *out, unsigned long long in, int len)
{
    if (len != sizeof(unsigned long long))
        return;
    char *p = (char *)(&in);
    for (int i = 0; i < 8; i++)
    {
        out[i] = p[8 - i - 1];
    }
}
int make_frame_data(my_msg_head *p_head, my_msg_data *p_data, my_msg_tail *p_tail, char *in, int in_size)
{
    int head_len = sizeof(my_msg_head);
    int data_len = sizeof(my_msg_data);
    int tail_len = sizeof(my_msg_tail);
    int total_len = head_len + data_len + tail_len;
    if (in_size < total_len)
    {
        return -1;
    }
    memcpy(in, p_head, head_len);
    memcpy(in + head_len, p_data, data_len);
    memcpy(in + head_len + data_len, p_tail, tail_len);
    return total_len;
}

main.c

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include "myprotocol.h"
void printData(char *data,int len)
{
    printf("data :\n");
    for(int i=0;i<len;i++)
    {
        printf("%02x ",(unsigned char)data[i]);
        if(i>0&&((i+1)%10==0))
        {
            printf("\n");
        }
    }
    printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
}
unsigned long long getTime_ms()
{
    struct timespec time1 = {0, 0}; 
    clock_gettime(CLOCK_REALTIME, &time1);   
    unsigned long long ret=((unsigned long long)time1.tv_sec)*1000+((unsigned long long)time1.tv_nsec)/1000/1000+8*60*60*1000;
    printData((char *)&ret,8);
    return ret;
}

int main(int argc, char **argv)
{
    char send_data[512]={0};
    my_msg_head m_head;
    my_msg_data m_data;
    my_msg_tail m_tail;
    memset(&m_head,0,sizeof(m_head));
    memset(&m_data,0,sizeof(m_data));
    memset(&m_tail,0,sizeof(m_tail));
    m_head.msg_head[0]=0x05;
    m_head.msg_head[1]=0x49;
    m_head.version[1]=0x01;
    m_head.version[0]=0x00;
    set_int_value_b(m_head.msg_num,0x1002,sizeof(m_head.msg_num));
    set_int_value_b(m_head.reply_num,0x20001,sizeof(m_head.reply_num));
    set_ulong_long_value_b(m_head.utc_time,getTime_ms(),sizeof(m_head.utc_time));
    set_int_value_b(m_head.data_len,sizeof(my_msg_data),sizeof(m_head.data_len));
    set_ulong_long_value_b(m_data.role_id,0x1234,sizeof(m_data.role_id));
    set_uint_value_b(m_data.move_type,(unsigned int)0x56789,sizeof(m_data.move_type));
    set_uint_value_b(m_data.distance,0x1234,sizeof(m_data.distance));
    set_ushort_value_b(m_data.speed,0x5678,sizeof(m_data.speed));
    m_tail.msg_tail[0]=0x05;
    m_tail.msg_tail[1]=0x49;
    int send_len=make_frame_data(&m_head,&m_data,&m_tail,send_data,sizeof(send_data));
    printData(send_data,send_len);
    /*
    小端:
        49 05 01 00 02 10 00 00 01 00  
        02 00 b6 04 9f b0 76 01 00 00  
        12 00 00 00 34 12 00 00 00 00 
        00 00 89 67 05 00 34 12 00 00
        78 56 49 05 
    大端:
        05 49 00 01 00 00 10 02 00 02 
        00 01 00 00 01 76 b0 9f 04 b6 
        00 00 00 12 00 00 00 00 00 00 
        12 34 00 05 67 89 00 00 12 34 
        56 78 05 49
    */
}

 

posted @ 2020-12-29 23:17  jest549  阅读(1109)  评论(0编辑  收藏  举报