Day3: Lars的回显功能+多路IO事件机制

1 回显功能

        逻辑:将数据读到input_buf中---->将input_buf存到业务的msg内存中进行业务处理---->将业务数据msg写到output_buf中---->将output_buf中的数据写到客户端套接字connfd中

            input_buf ibuf;
            output_buf obuf;
            int ret =0;
            char *msg = NULL;
            int msg_len = 0;

            do{
                ret = ibuf.read_data(connfd);
                if(ret==-1){
                    fprintf(stderr, "ibuf read_data error\n");
                    break;
                }

                //将ibuf数据进行业务处理
                msg_len  = ibuf.length();
                msg = (char*)malloc(msg_len);
                ZeroMemory(msg, msg_len);
                memcpy(msg, ibuf.data(), msg_len);

                ibuf.pop(msg_len);
                ibuf.adjust();

                printf("recv data=%s\n", msg);

                //将数据写到obuf
                obuf.send_data(msg, msg_len);
                while(obuf.length()){
                    int write_ret = obuf.write2fd(connfd);
                    if(write_ret==-1)
                    {
                        fprintf(stderr, "write2fd error\n");
                        return;
                    }
                    else if(write_ret==0){
                        continue;
                    }
                }
                free(msg);
            }while(ret!=0);
           
           //客户端已经关闭
           close(connfd);

2 多路IO事件机制 event_loop (基于epoll原生事件来封装)

2.1 event_base

        io_event:包含读回调及参数、写回调及参数

        io_callback:事件的回调函数

/*
定义IO复用机制事件的封装(epoll原生事件封装)
*/
class event_loop;
//IO事件触发的回调函数
typedef void io_callback(event_loop *loop, int fd, void *args);

//封装一次IO触发的事件
struct  io_event{
    io_event(){
    mask = 0;
    write_callback = NULL;
    read_callback = NULL;
    wcb_args = NULL;
    rcb_args = NULL;
    }

    //事件的读写属性
    int mask; //EPOLLIN, EPOLLOUT
    //读事件触发所绑定的回调函数
    io_callback *read_callback;
    //写事件触发所绑定的回调函数
    io_callback *write_callback;
    //读事件回调函数的形参
    void *rcb_args;
    //写事件回调函数形参
    void *wcb_args;
};

2.2 event_loop

2.2.1 属性

        _io_evs: <key, value>-------><fd, io_event>

        listen_fd_set:正在被监听的fd集合

2.2.2 方法

        add_io_event():添加一个事件

        delete_io_event():删除一个事件

#define MAXEVENTS 10
//map:<key, value>------><fd, io_event>
typedef std::unordered_map<int, io_event> io_event_map;
typedef std::unordered_map<int, io_event>::iterator io_event_map_it;

//set: fd
typedef std::unordered_set<int> listen_fd_set;

class event_loop
{
public:
    //创建epoll
    event_loop();
    //阻塞循环监听事件,并且处理
    void event_process();
    //添加一个io事件到event_pool中
    void add_io_envent(int fd, io_callback *proc, int mask, void *args);
    //删除一个io事件从event_pool中
    void delete_io_event(int fd);
    //删除一个io事件的某个触发条件(EPOLLIN/EPOOLOUT)
    void del_io_event(int fd, int mask);
private:
    int _epfd; //通过epoll_create创建

    //当前event_loop监控的fd和对应事件的关系
    io_event_map _io_evs; //关系表

    //当前event_loop都有哪些fd正在监听[epoll_wait()正在等待哪些fd触发状态]
    listen_fd_set listen_fd;

    //每次epoll_wait所返回的是被激活的事件集合
    struct epoll_event _fired_evs[MAXEVENTS];

};

3 LarsV0.3开发

        tcp_server(添加一个event_loop属性;tcp_server创建完listen_fd之后,将listen_fd绑定一个回调业务的读事件)------------->>>调用accept_callback(accpet得到一个新的connfd;将connfd的读事件和读回调server_rd_callback添加到event_loop中)------------->>>server_rd_callback(读取客户端数据;将connfd读事件删除,添加写事件和写回调server_wt_callback到event_loop中)------------->>>server_wt_callback(将数据写回客户端;将connfd写事件删除,添加读事件和读回调server_rd_callback到event_loop中。

void accept_callback(event_loop* loop, int fd, void *args);
void server_wt_callback(event_loop *loop, int fd, void *args);

//临时的收发消息结构
struct message{
    char data[m4k];
    char len;
};

void accept_callback(event_loop* loop, int fd, void *args)
{
    tcp_server *server = (tcp_server*)args;
    server->do_accept();
}

//客户端connfd注册的写事件的回调业务
void server_wt_callback(event_loop *loop, int fd, void *args)
{
    struct message *msg = (struct message*) args;
    output_buf obuf;

    //将msg加入到obuf
    obuf.send_data(msg->data, msg->len);
    while(obuf.length())
    {
        int write_num = obuf.write2fd(fd);
        if(write_num==-1)
        {
            fprintf(stderr, "write connfd error\n");
            return;
        }
        else if(write_num==0)
        {
            //当前不可写
            break;
        }
    } 

    //删除写事件  添加读事件
    loop->del_io_event(fd, EPOLLOUT);
    loop->add_io_envent(fd, server_rd_callback, EPOLLIN, msg);
}

//客户端connfd注册的读事件的回调业务
void server_rd_callback(event_loop *loop, int fd, void *args)
{
    struct message *msg = (struct message*) args;
    int ret = 0;
    input_buf ibuf;
    ret = ibuf.read_data(fd);
    if(ret==-1){
        fprintf(stderr, "ibuf_read errror\n");
        //当前的读事件删除
        loop->delete_io_event(fd);

        //关闭
        close(fd);
        return ;
    }

    if(ret==0)
    {
        //对方正常关闭,当前的读事件删除
        loop->delete_io_event(fd);
        close(fd);
        return ;
    }

    //将读到的数据拷贝到msg中
    msg->len = ibuf.length();
    ZeroMemory(msg->data, msg->len);
    memcpy(msg->data, ibuf.data(), msg->len);

    ibuf.pop(msg->len);
    ibuf.adjust();
    printf("recv data = %s\n", msg->data);

    //删除读事件,添加写事件
    loop->del_io_event(fd, EPOLLIN);
    loop->add_io_envent(fd, server_wt_callback, EPOLLOUT, msg); //epoll_wait会立刻触发EPOLLOUT事件
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值