在自己开发服务器软件的时候遇到的问题,如果使用纯粹的char或者文本进行数据通信的话,可读性差不说,而且很容易被截取破解,所以萌生了一个开发自己通信协议的想法,本文章的思路借鉴了 Charles0429 在github上的项目的思想。
在本文章里面,我们数据通信统一采用一个结构体来进行数据通信与传输,它包含一个标志头,数据体与校验码,校验码来保证数据传输的正确性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#define HEAD_SIZE sizeof(package_head_t)
#define PACKAGE_SIZE sizeof(package_t)
#define CS_SIZE (16 * sizeof(uint8_t))
typedef struct package_head
{
uint8_t type; /*表明数据类型*/
uint32_t lenght /*表明整个数据的长度*/
}package_head_t;
typedef struct package
{
package_head_t head;
char* data; /*传输的具体数据*/
uint8_t CS[16]; /*MD5数据校验,可选*/
}package_t;
|
以上代码需要包含以下头文件:
1
2
3
4
|
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <stdint.h>
|
有了基本的结构定义,那么我们就要对这些进行具体操作了,首先来看看我们的第一个函数。
1
|
package_t *package_read(int socket_fd);
|
这个函数拥有一个package_t指针,用来指向已经读取完成了的package。他还有一个参数socket_fd,用来确定从哪个套接字描述符来读取package。
下面我们来看看具体的实现:
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
|
package_t *package_read(int socket_fd)
{
int recv_len; /*已经接收到的总字节数*/
int data_len; /*数据体的长度*/
int len; /*recv接收到的字节数*/
package_t *tmp = (package_t*)malloc(PACKAGE_SIZE);
/*接受头部信息*/
while(recv_len<HEAD_SIZE)
{
len=recv(socket_fd,tmp,HEAD_SIZE-recv_len,0);
if(len>0)
{
recv_len+=len;
}
}
recv_len=0;
data_lenght=get_lenght(tmp); /*获取数据长度*/
/*初始化数据体*/
tmp->data=(char*)malloc(sizeof(char)*data_lenght);
/*接受数据体*/
while(recv_len<data_lenght)
{
len=recv(socket_fd,tmp,data_lenght-recv_len,0);
if(len>0)
{
recv_len+=len;
}
}
recv_len=0;
while(recv_len<CS_SIZE)
{
len=recv(socket_fd,tmp_data,CS_SIZE-recv_len,0);
if(len>0)
{
recv_len+=len;
}
}
}
|
上面用到了一个函数get_lenght(),实际就是取package的数据体长度。
1
2
3
4
|
uint32_t get_lenght(package_t *pack)
{
return pack->data_lenght;
}
|
这个代码思路很简单,依次使用recv读取到数据,每次读取之后的len长度相加,直到读取完成。
下面再写一个发送package_t的函数,用户将我们的数据发送给 服务端/客户端。
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
|
void package_write(int socket_fd,void *package)
{
int send_len;
int len;
int data_lenght;
package_t *tmp = (package_t*)package;
while(send_len<HIDE_SIZE)
{
len=send(socket_fd,tmp,HEAD_SIZE-send_len);
if(len>0)
{
send_len+=len;
}
}
send_len=0;
data_lenght=get_lenght(tmp);
while(send_len<data_lenght)
{
len=send(socket_fd,tmp->data,data_lenght-send_len);
if(len>0)
{
send+=len;
}
}
send_len=0;
while(send_len<CS_SIZE)
{
len=send(socket_fd,tmp->CS,CS_SIZE-send_len);
if(len>0)
{
send_len+=len;
}
}
}
|