嵌入式通信协议制作demo 服务端和客户端代码 同时支持大小端模式

服务端

data_frame结构体是我们的通信协议

#include <stdint.h>
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "log.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<errno.h>
#include <sys/types.h>
#include <signal.h>

#define    CMD_HEAD_FRAME                            0x6666bbbb
#define    CMD_TAIL_FRAME                            0x8888dddd

typedef uint64_t u64;
typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef struct {
        u32 head;
        u16 cmd;
        u32 len;
        u8 *data;
        u16 crc;
        u32 tail;
}data_frame;


// Switch the byte order of the data
u16 byte_order_switch16(u16 data)
{
        u16 temp = 0;
        temp = (data & 0xff) << 8;
        temp |= (data & 0xff00) >> 8;
        return temp;
}

u32 byte_order_switch32(u32 data)
{
        u32 temp = 0;
        temp = (data & 0xff) << 24;
        temp |= (data & 0xff00) << 8;
        temp |= (data & 0xff0000) >> 8;
        temp |= (data & 0xff000000) >> 24;
        return temp;
}

u64 byte_order_switch64(u64 data)
{
        u64 temp = 0;
        temp = (data & 0xff) << 56;
        temp |= (data & 0xff00) << 40;
        temp |= (data & 0xff0000) << 24;
        temp |= (data & 0xff000000) << 8;
        temp |= (data & 0xff00000000) >> 8;
        temp |= (data & 0xff0000000000) >> 24;
        temp |= (data & 0xff000000000000) >> 40;
        temp |= (data & 0xff00000000000000) >> 56;
        return temp;
}

u8 *data_frame_to_buf_big(data_frame *frame,int *data_len)
{
        u8 *buf = NULL;
        u8 *p = NULL;
        u16 crc = 0;
        u32 len = 0;
        u32 i = 0;

        if (frame == NULL) {
                return NULL;
        }

        len = frame->len + 16;
        buf = (u8 *)malloc(len);
        if (buf == NULL) {
                return NULL;
        }

        p = buf;
        *(u32 *)p = byte_order_switch32(frame->head);
        p += 4;
        *(u16 *)p = byte_order_switch16(frame->cmd);
        p += 2;
        *(u32 *)p = byte_order_switch32(frame->len);
        p += 4;
        memcpy(p, frame->data, frame->len);
        p += frame->len;
        *(u16 *)p = byte_order_switch16(frame->crc);
        p += 2;
        *(u32 *)p = byte_order_switch32(frame->tail);

        *data_len = len;

        return buf;
}

u8 *data_frame_to_buf_little(data_frame *frame,int *data_len)
{
        u8 *buf = NULL;
        u8 *p = NULL;
        u16 crc = 0;
        u32 len = 0;
        u32 i = 0;

        if (frame == NULL) {
                return NULL;
        }

        len = frame->len + 16;
        buf = (u8 *)malloc(len);
        if (buf == NULL) {
                return NULL;
        }

        p = buf;
        *(u32 *)p = frame->head;
        p += 4;
        *(u16 *)p = frame->cmd;
        p += 2;
        *(u32 *)p = frame->len;
        p += 4;
        memcpy(p, frame->data, frame->len);
        p += frame->len;
        *(u16 *)p = frame->crc;
        p += 2;
        *(u32 *)p = frame->tail;

        *data_len = len;

        return buf;
}

// 构造帧
data_frame *create_frame(u16 cmd, u8 *data, u32 len)
{
        data_frame *frame = NULL;
        u8 *buf = NULL;
        u16 crc = 0;
        u32 i = 0;

        if (data == NULL) {
                return NULL;
        }

        frame = (data_frame *)malloc(sizeof(data_frame));
        if (frame == NULL) {
                return NULL;
        }

        frame->head = CMD_HEAD_FRAME;
        frame->cmd = cmd;
        frame->len = len;
        frame->data = (u8 *)malloc(len);
        if (frame->data == NULL) {
                free(frame);
                return NULL;
        }
        memcpy(frame->data, data, len);
        frame->crc = crc;
        frame->tail = CMD_TAIL_FRAME;

        return frame;
}


void free_data_frame(data_frame *frame)
{
        if (frame == NULL) {
                return;
        }

        if (frame->data != NULL) {
                free(frame->data);
                frame->data = NULL;
        }

        free(frame);
        frame = NULL;
}

// create tcp socket server
int create_tcp_server(int port)
{
        int listenfd;
        struct sockaddr_in servaddr;

        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd == -1) {
                log_error("create socket error: %s(errno: %d)", strerror(errno), errno);
                return -1;
        }

        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(port);

        int opt = 1;
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));

        if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
                log_error("bind socket error: %s(errno: %d)", strerror(errno), errno);
                return -1;
        }
        // 复用地址和端口
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));

       

        if (listen(listenfd, 10) == -1) {
                log_error("listen socket error: %s(errno: %d)", strerror(errno), errno);
                return -1;
        }

        log_info("======waiting for client's request======");
        return listenfd;
}


// 接受ctrl+c信号 退出 
void sigint_handler(int sig)
{
        log_info("catch signal %d", sig);
        exit(0);
}


int main(){
    // 注册ctrl+c信号
    signal(SIGINT, sigint_handler);


    static u8 data_send[100] = {0};
    static u8 *data_frame_buf = NULL;
    static u8 *data = "1234567890";
    log_info("data len = %d", strlen(data));
    u8 len = strlen(data) + 1;
    u32 total_len = 0;
    data_frame *frame = NULL;
    frame = create_frame(0x1234, data, len);
    data_frame_buf = data_frame_to_buf_little(frame, &total_len);

  
    for(int i = 0;i < total_len;i++){
        printf("%02x ",data_frame_buf[i]);
    }
      
    int listenfd = create_tcp_server(6666);
    if (listenfd == -1) {
        log_error("create tcp server error");
        return -1;
    }
    // 复用地址和端口
   

    // accept client
    int connfd;
    struct sockaddr_in cliaddr;
    socklen_t clilen = sizeof(cliaddr);
    connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
    if (connfd == -1) {
        log_error("accept socket error: %s(errno: %d)", strerror(errno), errno);
        return -1;
    }
    log_info("accept client: %s:%d", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);

    // send data
    while(1){

        int send_len = send(connfd, data_frame_buf, total_len, 0);
        if (send_len == -1) {
            log_error("send data error: %s(errno: %d)", strerror(errno), errno);
            return -1;
        }
        for(int i = 0; i < total_len; i++){
            printf("%02x ", data_frame_buf[i]);
        }
        fflush(stdout);
        sleep(5);
    }
    free_data_frame(data_frame_buf);
 
}

客户端

#include <stdint.h>
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "log.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<errno.h>

#define    CMD_HEAD_FRAME                            0x6666bbbb
#define    CMD_TAIL_FRAME                            0x8888dddd

typedef uint64_t u64;
typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef struct {
        u32 head;
        u16 cmd;
        u32 len;
        u8 *data;
        u16 crc;
        u32 tail;
}data_frame;


// create tcp socket client
int create_tcp_client(char *ip, int port)
{
        int sockfd;
        struct sockaddr_in servaddr;

        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                log_error("create socket error: %s(errno: %d)", strerror(errno), errno);
                return -1;
        }

        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(port);
        if (inet_pton(AF_INET, ip, &servaddr.sin_addr) <= 0) {
                log_error("inet_pton error for %s", ip);
                return -1;
        }

        if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
                log_error("connect error: %s(errno: %d)", strerror(errno), errno);
                return -1;
        }
        return sockfd;
}

// 根据data_frame结构体解析协议 接受的数据是大端的 按照大端的方式解析
int parse_data_frame_big(data_frame *frame, u8 *data, int len)
{
        int i = 0;
        u8 *p = data;
        u16 crc = 0;
        u32 head = 0;
        u32 tail = 0;
        u16 cmd = 0;
        u32 data_len = 0;
        u8 *data_buf = NULL;

        // if (len < 12) {
        //         log_error("data len error");
        //         return -1;
        // }
        // 0x6666bbbb 如果是大端的话 0x66在前面 0xbb在后面

        head = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
        if (head != CMD_HEAD_FRAME) {
                log_error("head error");
                return -1;
        }
        p += 4;

        cmd = (p[0] << 8) | p[1];
        p += 2;

        data_len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
        p += 4;

        if (data_len > 0) {
                data_buf = (u8 *)malloc(data_len);
                if (data_buf == NULL) {
                        log_error("malloc error");
                        return -1;
                }
                memcpy(data_buf, p, data_len);
                p += data_len;
        }

        crc = (p[0] << 8) | p[1];
        p += 2;

        tail = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
        if (tail != CMD_TAIL_FRAME) {
                log_error("tail error");
                return -1;
        }

        frame->head = head;
        frame->cmd = cmd;
        frame->len = data_len;
        frame->data = data_buf;
        frame->crc = crc;
        frame->tail = tail;

        return 0;
}


// int parse_data_frame_small





// 根据data_frame解析协议
int parse_data_frame_little(data_frame *frame, u8 *data, u32 len)
{
        u32 i = 0;
        u32 head = 0;
        u32 tail = 0;
        u16 crc = 0;
        u32 data_len = 0;
        u8 *data_buf = NULL;

        // if (len < sizeof(data_frame)) {
        //         log_error("data len is too short");
        //         return -1;
        // }

        memcpy(&head, data, sizeof(u32));
        if (head != CMD_HEAD_FRAME) {
                log_error("head frame error");
                return -1;
        }

        memcpy(&frame->cmd, data + sizeof(u32), sizeof(u16));
        memcpy(&data_len, data + sizeof(u32) + sizeof(u16), sizeof(u32));
        if (data_len > 0) {
                data_buf = (u8 *)malloc(data_len);
                if (data_buf == NULL) {
                        log_error("malloc error");
                        return -1;
                }
                memcpy(data_buf, data + sizeof(u32) + sizeof(u16) + sizeof(u32), data_len);
                frame->data = data_buf;
        }
        memcpy(&crc, data + sizeof(u32) + sizeof(u16) + sizeof(u32) + data_len, sizeof(u16));
        memcpy(&tail, data + sizeof(u32) + sizeof(u16) + sizeof(u32) + data_len + sizeof(u16), sizeof(u32));
        if (tail != CMD_TAIL_FRAME) {
                log_error("tail frame error");
                return -1;
        }

        frame->head = head;
        frame->len = data_len;
        frame->crc = crc;
        frame->tail = tail;

        return 0;
}

int main(){
    // connect port 6666
    int sockfd = create_tcp_client("127.0.0.1", 6666);
    if (sockfd < 0) {
        log_error("create tcp client error");
        return -1;
    }
    log_info("create tcp client success");
    // receive data
    u8 recvline[4096];
    data_frame rev_frame;
    memset(&rev_frame, 0, sizeof(data_frame));
    while (1) {
        int n = recv(sockfd, recvline, 4096, 0);
        if (n < 0) {
            log_error("recv error: %s(errno: %d)", strerror(errno), errno);
            return -1;
        }
        recvline[n] = '\0';
        for (int i = 0; i < n; i++) {
            printf("%02x ", recvline[i]);
        }
        parse_data_frame_little(&rev_frame, recvline, n);
        log_info("cmd: %0x, len: %0x, crc: %0x ,head: %0x, tail: %0x", rev_frame.cmd, rev_frame.len, rev_frame.crc, rev_frame.head, rev_frame.tail);
        if (rev_frame.data != NULL) {
            log_info("data: %s", rev_frame.data);
        }

        printf("\r\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值