IOCP 二进制协议 分包

一、IOCP 二进制协议分包的思路

  1. 解析数据头,获取协议包体的大小,判断是否收到一个完整的数据头,
    如果不是,继续投递recv请求,直到收到一个数据头

  2. 异常的数据包,关闭session (pkg_size > MAX_PKG_SIZE)

  3. 全部数据收到,进行处理.

    1 判断long_pkg是否存在,如果存在,就要释放
    2.如果收到数据 > pkg_size,io_data->pkg指向正确的位置
    3.如果收到数据 = 0,那么就继续投递recv请求

  4. 没有收到全部数据
    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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值