服务端
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");
}
}