一、IOCP 二进制协议分包的思路
解析数据头,获取协议包体的大小,判断是否收到一个完整的数据头,
如果不是,继续投递recv请求,直到收到一个数据头异常的数据包,关闭session (pkg_size > MAX_PKG_SIZE)
全部数据收到,进行处理.
1 判断long_pkg是否存在,如果存在,就要释放
2.如果收到数据 > pkg_size,io_data->pkg指向正确的位置
3.如果收到数据 = 0,那么就继续投递recv请求没有收到全部数据
1.pkg_size > MAX_RECV_SIZE,那么就申请内存空间!存放pkg,否则继续收数据
2.继续投递请求
二、代码实现
1.获取收到的数据的长度
static int read_header(unsigned char* header, int len, int* pkg_size){
if (len < 2){
return -1;
}
int size = (header[0]) | (header[1] << 8);
*pkg_size = size;
return 0;
}
2.接受数据的结构
struct io_package {
WSAOVERLAPPED overlapped;
WSABUF wsabuffer;
int opt; // 标记一下我们当前的请求的类型;
int accpet_sock;
int recved;
unsigned char* long_pkg;
unsigned char pkg[MAX_RECV_SIZE];
};
3.对收到数据进行分包
case IOCP_RECV: { // 完成端口意味着数据已经读好
io_data->recved += dwTrans;
while (io_data->recved > 0)
{
int pkg_size = 0;
if (read_header(io_data->pkg, io_data->recved, &pkg_size) < 0){// 不够读取包头size大小
io_data->wsabuffer.buf = io_data->pkg + io_data->recved;
io_data->wsabuffer.len = MAX_RECV_SIZE - io_data->recved;
// 当读的请求完成后,必须要再加一个读的请求;
DWORD dwRecv = 0;
DWORD dwFlags = 0;
int ret = WSARecv(s->c_sock, &(io_data->wsabuffer),1,&dwRecv,&dwFlags,&(io_data->overlapped),NULL);
break;
}
if (pkg_size > MAX_PKG_SIZE){
close_session(s);
free(io_data);
}
if (io_data->recved >= pkg_size){ // 全部收到,进行处理
char* pkg = (io_data->long_pkg == NULL) ? io_data->pkg : io_data->long_pkg;
on_server_recv(s, pkg + 2, pkg_size - 2);
if (io_data->long_pkg != NULL){
free(io_data->long_pkg);
io_data->long_pkg = NULL;
}
if (io_data->recved > pkg_size){
memmove(io_data->pkg, io_data->pkg + pkg_size, pkg_size - io_data->recved);
}
io_data->recved -= pkg_size;
if (io_data->recved == 0){
io_data->wsabuffer.buf = io_data->pkg + io_data->recved;
io_data->wsabuffer.len = MAX_RECV_SIZE - io_data->recved;
// 当读的请求完成后,你必须要再加一个读的请求;
DWORD dwRecv = 0;
DWORD dwFlags = 0;
int ret = WSARecv(s->c_sock, &(io_data->wsabuffer),
1, &dwRecv, &dwFlags,
&(io_data->overlapped), NULL);
break;
}
}
else{//没有读完
if (pkg_size > MAX_RECV_SIZE){
if (io_data->long_pkg == NULL) {
io_data->long_pkg = malloc(pkg_size);
memcpy(io_data->long_pkg, io_data->pkg, io_data->recved);
}
io_data->wsabuffer.buf = io_data->long_pkg + io_data->recved;
io_data->wsabuffer.len = pkg_size - io_data->recved;
}
else{
io_data->wsabuffer.buf = io_data->pkg + io_data->recved;
io_data->wsabuffer.len = pkg_size - io_data->recved;
}
// 当读的请求完成后,你必须要再加一个读的请求;
DWORD dwRecv = 0;
DWORD dwFlags = 0;
int ret = WSARecv(s->c_sock, &(io_data->wsabuffer),
1, &dwRecv, &dwFlags,
&(io_data->overlapped), NULL);
break;
}
}
}
转载请说明出处:http://blog.csdn.net/u013158916/article/details/54271180