Server-side example of libevent(13) bufferevent

1. Server-side example 1

test_bufferevent1.cpp:

#include <iostream>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <thread>
#include <errno.h>
#include <string.h>
#ifndef _WIN32
#include <signal.h>
#else
#endif
using namespace std;
#define PORT 5001

void read_cb(bufferevent *be, void *arg){
    cout <<"read_cb "<<flush;
	
	//读取输入缓冲数据
	char data[1024] = {0};
	int len = bufferevent_read(be,data,sizeof(data)-1);
	cout<<"["<<data<<"]"<<endl;
	if(len <=0 ) return;
	
	if(strstr(data,"quit") != NULL){
	    cout<<"quit"<<endl;
		//退出并关闭socket
		bufferevent_free(be);
	}
	//发送数据 写入到输出缓冲
	bufferevent_write(be,"OK",3);
}

void write_cb(bufferevent *be, void *arg){
    cout <<"write_cb "<<flush;
}

//错误、超时、链接断开时会进入
void event_cb(bufferevent *be, short events, void *arg){
    cout <<"event_cb "<<flush;
}

void listen_cb(evconnlistener *ev, evutil_socket_t s, sockaddr* sin, int slen, void *arg){
    cout<<"listen_cb "<<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_setcb(bev, read_cb, write_cb, event_cb, base);
}

int main(int argc, char *argv[])
{
#ifdef _WIN32
	WSADATA wsa;
	int a = WSAStartup(MAKEWORD(2, 2), &wsa);   
#else
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		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(PORT);
	
	evconnlistener *ev = evconnlistener_new_bind(base,
	        listen_cb, //回调函数
			base, //回调函数的参数arg
			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
			10, //listen back
			(sockaddr*)&sin,
			sizeof(sin)
			);
    
	//进入事件主循环
	event_base_dispatch(base);
	//释放资源
	evconnlistener_free(ev);
	event_base_free(base);
    return 0;
}

Two, server-side example 2

Added "Water Level for Read and Write" parameter.

 

test_bufferevent2.cpp:

#include <iostream>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <thread>
#include <errno.h>
#include <string.h>
#ifndef _WIN32
#include <signal.h>
#else
#endif
using namespace std;
#define PORT 5001

void read_cb(bufferevent *be, void *arg){
    cout <<"read_cb "<<flush;
	
	//读取输入缓冲数据
	char data[1024] = {0};
	int len = bufferevent_read(be,data,sizeof(data)-1);
	cout<<"["<<data<<"]"<<endl;
	if(len <=0 ) return;
	
	if(strstr(data,"quit") != NULL){
	    cout<<"quit"<<endl;
		//退出并关闭socket
		bufferevent_free(be);
	}
	//发送数据 写入到输出缓冲
	bufferevent_write(be,"OK",3);
}

void write_cb(bufferevent *be, void *arg){
    cout <<"write_cb "<<flush;
}

//错误、超时、链接断开时会进入
void event_cb(bufferevent *be, short events, void *arg){
    cout <<"event_cb "<<flush;
	//读取超时事件发生后,数据读取停止
	if(events & BEV_EVENT_TIMEOUT){
	    cout<<"BEV_EVENT_TIMEOUT"<<endl;
		//可清除无效的连接
		bufferevent_free(be);
	}else if(events & BEV_EVENT_ERROR){
	    //可清除无效的连接
	    bufferevent_free(be);
	}else{
	    cout<<"OTHERS"<<endl;
	}
}

void listen_cb(evconnlistener *ev, evutil_socket_t s, sockaddr* sin, int slen, void *arg){
    cout<<"listen_cb "<<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就是无限制,默认值 -- 数据超过高水位时,会被分解成多条发送
	        );
	
	bufferevent_setwatermark(bev, EV_WRITE,
	        5,//低水位 0就是无限制,默认值 -- 缓冲数据低于低水位,写入回调被调用
			0 //高水位无效
	        );	
	
	//超时时间的设置
	timeval t1 = {3, 0}; //3秒
	bufferevent_set_timeouts(bev, &t1, 0); //3秒读取超时 超时触发event_cb
	
	//设置回调函数
	bufferevent_setcb(bev, read_cb, write_cb, event_cb, base);
}

int main(int argc, char *argv[])
{
#ifdef _WIN32
	WSADATA wsa;
	int a = WSAStartup(MAKEWORD(2, 2), &wsa);   
#else
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		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(PORT);
	
	evconnlistener *ev = evconnlistener_new_bind(base,
	        listen_cb, //回调函数
			base, //回调函数的参数arg
			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
			10, //listen back
			(sockaddr*)&sin,
			sizeof(sin)
			);
	
	//进入事件主循环
	event_base_dispatch(base);
	//释放资源
	evconnlistener_free(ev);
	event_base_free(base);
    return 0;
}

Guess you like

Origin blog.csdn.net/mars21/article/details/131392824