libevent6:bufferevent

git地址: http://121.4.70.4:3000/adminPyf/libevent_study.git
libevent_study/test_buffer_client

以下代码就是简单的开一个服务器,从bufferevent得到数据
详细注释代码里很详细,LINUX、Windows都编译过

#include <iostream>
#include <event2/event.h>
#include <event2/thread.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>


#ifdef _WIN32
#include <string>
#else
#include <signal.h>
#include <string.h>
#endif // !_WIN32

using namespace std;

static string recvstr = "";
static int recvCount = 0 ;
static int sendCount = 0 ;

void read_cb(bufferevent * bev,void *arg){
    cout  << "[R]" <<endl;

    char data[1024] = {0};
    int len = bufferevent_read(bev,data,sizeof(data)-1);
    if(len<=0)return ;
    recvstr += data;
    recvCount+=len;

   /* if(strstr(data,"quit")!= NULL){
        cout << "quit" << endl;  
        bufferevent_free(bev); // BEV_OPT_CLOSE_ON_FREE 设置了这个才会关闭 
    } */
    //发送数据 写入到输出缓冲
    bufferevent_write(bev,"ok",3);
}

void write_cb(bufferevent * bev,void *arg){
    cout  << "[W]" <<endl;
}

//错误 超时 连接断开会进入
void event_cb(struct bufferevent *bev, short what, void *ctx){
    cout  << "[CB]" <<endl;

    //读取超时事件发生后,数据读取停止
    if(what & BEV_EVENT_TIMEOUT  && what & BEV_EVENT_READING ){
        char data[1024]={0};
        int len = bufferevent_read(bev,data,sizeof(data)-1);
        if(len > 0){
            recvCount += len;
            recvstr += data;
        }
        cout << "read timeout " << endl;

        //bufferevent_enable(bev,EV_READ); //可以重新设置
        bufferevent_free(bev);
        cout << recvstr << endl;
        cout << "recvCOunt" << recvCount << "  sendCount" <<sendCount << endl;

    }else if(what & BEV_EVENT_ERROR){
        bufferevent_free(bev);
    }
    else{
        cout << "other " << endl;
    }
}

void listen_cb(struct evconnlistener *ev, evutil_socket_t s,
               struct sockaddr *insin, int socklen, void *arg)
{
    cout << "listen_cb" << endl;

    struct sockaddr_in *sin = (struct sockaddr_in *)&insin;
    int port = ntohs(sin->sin_port);

    char ip[16] = {0};
    evutil_inet_ntop(AF_INET, &sin->sin_addr  ,ip,sizeof(ip)-1);
    cout << "client ip is " << ip    << "port is " << port << endl;


    event_base* base = (event_base*)arg;
    //创建bufferevent上下文 BEV_OPT_CLOSE_ON_FREE清理bufferevent时关闭socket
    bufferevent * bev = bufferevent_socket_new(base,s,BEV_OPT_CLOSE_ON_FREE);
    bufferevent_enable(bev,EV_READ|EV_WRITE);

    //设置水位
    //读取水位
    bufferevent_setwatermark(bev,EV_READ,
    10, //低水位0就是无限制 默认0   有10个数据才会回调函数被调用
    10); //高水位0就是无限制 默认0  超过10的数据会拆分成多个10调用多次

    bufferevent_setwatermark(bev,EV_WRITE,
    5, // 低水位0就是无限制 默认0    缓冲数据低于5 写入回调内调用
    0); //暂时无效

    timeval t1 = {0,50000};
    bufferevent_set_timeouts(bev,&t1,NULL);
    bufferevent_setcb(bev,read_cb,write_cb,event_cb,base);
}

void clinet_read_cb(bufferevent * bev,void *arg){
    cout  << "[clinet R]" <<endl;
    char data[1024] = {0};
    int len = bufferevent_read(bev,data,sizeof(data)-1);
    if(len<=0)return ;
    cout << "[" << data << "]" <<endl;
   /* if(strstr(data,"quit")!= NULL){
        cout << "quit" << endl;  
        bufferevent_free(bev); // BEV_OPT_CLOSE_ON_FREE 设置了这个才会关闭 
    } */
    //发送数据 写入到输出缓冲
    //bufferevent_write(bev,"ok",3);
}

void clinet_write_cb(bufferevent * bev,void *arg){
    cout  << "[clinet W]" <<endl;
    //激活write
    FILE *fp = (FILE *)arg;
    char data[1024]={0};
    int len = fread(data,1,sizeof(data)-1,fp);
    if(len <= 0){
        // 读到文件结尾或者文件出错
        fclose(fp);
        //立刻清理 可能会造成缓冲数据没有发送结束 !! 不能在这里做
        //bufferevent_free(bev);
        bufferevent_disable(bev,EV_WRITE);
        return ;
    }
    sendCount += len;
    bufferevent_write(bev,data,len);

}

//错误 超时 连接断开都会进入
void clinet_event_cb(struct bufferevent *bev, short what, void *ctx){
    cout  << "[ clinet CB]" <<endl;

    //读取超时事件发生后,数据读取停止
    if(what & BEV_EVENT_TIMEOUT  && what & BEV_EVENT_READING ){
        cout << "read timeout " << endl;

        //bufferevent_enable(bev,EV_READ); //可以重新设置
        bufferevent_free(bev);
        return ;

    }else if(what & BEV_EVENT_ERROR){
        bufferevent_free(bev);
        return ;
    }

    //服务端的关闭事件 
    if(what & BEV_EVENT_EOF){
        cout << "BEV_EVENT_EOF" << endl;
        bufferevent_free(bev);
    }

    if(what & BEV_EVENT_CONNECTED){
        cout << "BEV_EVENT_CONNECTED " << endl;
        bufferevent_trigger(bev,EV_WRITE,0); //触发写事件
    }
}

int main(int agrc, char **agrv)
{

#ifdef _WIN32
    //初始化socket库
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);
#else
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
    { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
        return 1;
    }
#endif

    //创建网络服务器
    event_base *base = event_base_new();
    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5001);

    evconnlistener_new_bind(base,
                            listen_cb,
                            base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
                            10,
                            (sockaddr *)&sin,
                            sizeof(sin));

{ //防止变量名重定义
    //调用客户端代码  
    // -1 内部创建socket
    bufferevent * bev = bufferevent_socket_new(base,-1,BEV_OPT_CLOSE_ON_FREE);
    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5001);
    evutil_inet_pton(AF_INET,"127.0.0.1",&sin.sin_addr.s_addr);

    FILE *fp = fopen("test_buffer_client.cpp","rb");
    //设置回调函数
    bufferevent_setcb(bev,clinet_read_cb,clinet_write_cb,clinet_event_cb,fp);
    bufferevent_enable(bev,EV_READ|EV_WRITE);
    int ret = bufferevent_socket_connect(bev,(sockaddr*)&sin,sizeof(sin) );
    if(ret == 0){
        cout << "connected" <<endl;
    }
}
    //进入事件主循环
    event_base_dispatch(base);
    event_base_free(base);

    return 0;
}
libevent6:bufferevent

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动到顶部