其他分享
首页 > 其他分享> > libevent(九)bufferevent 客户端测试

libevent(九)bufferevent 客户端测试

作者:互联网

在这里插入图片描述

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


static string recv_str = "";
static int recv_count = 0;
static int send_count = 0;

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

	//读取超时事件发生后,数据读取停止
	if (events & BEV_EVENT_TIMEOUT && events & BEV_EVENT_READING)
	{
		//读取缓冲中数据
		char data[1024] = { 0 };
		int len = bufferevent_read(be, data, sizeof(data) - 1);
		if (len > 0) {
			recv_str += data;
			recv_count += len;
		}
		cout << "server BEV_EVENT_TIMEOUT | BEV_EVENT_READING" << endl;
		bufferevent_free(be);
		cout << recv_str << endl;
		cout << "recv_count= " << recv_count <<"\tsend_count= " << send_count << endl;
	}
	else if (events & BEV_EVENT_ERROR)
	{
		bufferevent_free(be);
	}
	
}


void read_cb(bufferevent* be, void* arg) {
	cout << "read buffer data[R]" << flush;
	char data[1024] = { 0 };

	//读取输入缓冲数据
	int len = bufferevent_read(be, data, sizeof(data) - 1);
	cout << data << endl;
	if (len <= 0)return;
	recv_str += data;
	recv_count += len;

	//if (strstr(data, "quit") != NULL) {
	//	cout << "quit and close socket!" << endl;
	//	bufferevent_free(be);
	//}
	//发送数据,写入到输出缓冲
	bufferevent_write(be, "OK", 3);
}


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


void client_event_cb(bufferevent* be, short events, void* arg) {
	cout << "[client_E]" << flush;

	//读取超时事件发生后,数据读取停止
	if (events & BEV_EVENT_TIMEOUT && events & BEV_EVENT_READING)
	{
		cout << "client BEV_EVENT_TIMEOUT | BEV_EVENT_READING" << endl;
		bufferevent_free(be);
		return;
	}
	else if (events & BEV_EVENT_ERROR)
	{
		bufferevent_free(be);
		return;
	}
	//服务端的正常关闭事件
	if (events & BEV_EVENT_EOF) {
		cout << "BEV_EVENT_EOF" << endl;
		bufferevent_free(be);
	}
	if (events&BEV_EVENT_CONNECTED)
	{
		cout << "BEV_EVENT_CONNECTED > activate client write" << endl;
		bufferevent_trigger(be, EV_WRITE, 0);
	}
}

void client_read_cb(bufferevent* be, void* arg) {
	cout << "read buffer data[client_R]" << 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 and close socket!" << endl;
	//	bufferevent_free(be);
	//}
	//发送数据,写入到输出缓冲
	bufferevent_write(be, "OK", 3);
}

void client_write_cb(bufferevent* be, void* arg) {
	cout << "[client_W]" << flush;
	FILE* fp = (FILE*)arg;
	char data[1024] = { 0 };
	int len = fread(data, 1, sizeof(data) - 1, fp);
	if (len <= 0) 
	{
		//读到文件结尾或出错
		fclose(fp);

		//立刻清理,可能会造成缓冲数据没有发送结束
		//bufferevent_free(be);
		bufferevent_disable(be, EV_WRITE);
		return;
	}
	send_count += len;
	bufferevent_write(be, data, len);
}



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上下文(清理bufferevent时关闭socket)
	bufferevent* bev = bufferevent_socket_new(base, s, BEV_OPT_CLOSE_ON_FREE);

	//添加监控事件(读写)
	bufferevent_enable(bev, EV_READ | EV_WRITE);

	//设置水位 -- 读取水位(low_water=10, hight_water=0, 0表示无限制), 发送的数据至少10个字符,回调函数才被调用
	//设置水位 -- 写入水位(low_water=10, hight_water=0, 0表示无限制), 少于5个字符,回调函数被调用
	bufferevent_setwatermark(bev, EV_READ, 10, 0);
	bufferevent_setwatermark(bev, EV_WRITE, 5, 0);

	//超时时间的设置
	timeval t1 = { 3,0 };
	bufferevent_set_timeouts(bev, &t1, 0);

	//设置回调函数
	bufferevent_setcb(bev, read_cb, write_cb, event_cb, base);
}



int main(int argc, char** argv) {
#if _WIN32
	//windowns 初始化socket库
	WSADATA wsa;
	WSAStartup(MAKEWORD(2, 2), &wsa);
#else
	//linux 忽略管道信号,发送数据给已关闭的socket
	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(SPORT);
	evconnlistener* ev = evconnlistener_new_bind(
		base,
		listen_cb, //回调函数
		base,      //回调函数的参数arg
		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(SPORT);
		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, client_read_cb, client_write_cb, client_event_cb, fp);
		bufferevent_enable(bev, EV_READ | EV_WRITE);
		int re = bufferevent_socket_connect(bev, (sockaddr*)&sin, sizeof(sin));
		if (re == 0)
		{
			cout << "connected" << endl;
		}
	}
	
	//进入事件主循环
	event_base_dispatch(base);
	evconnlistener_free(ev);
	event_base_free(base);

#ifdef _WIN32
	WSACleanup();
#endif // _WIN32
	return 0;
}

标签:cout,int,bufferevent,libevent,cb,data,sin,客户端
来源: https://blog.csdn.net/wsp_1138886114/article/details/120988499