libevent tcp 简单通信 (二)

客户端

#pragma once
#include <event2/util.h>

class libevent_client
{
public:
	libevent_client();
	~libevent_client();

	void initial(int port);

	void connect_communicate();

private:
	struct sockaddr_in m_sin;
	int m_port;
	evutil_socket_t m_fd;
	struct event_base *m_base;
	struct bufferevent *m_bev;
	struct event *m_event;


private:
	static void read_cb(struct bufferevent *bev, void *arg);

	static void write_cb(struct bufferevent *bev, void *arg);

	static void event_cb(struct bufferevent *bev, short events, void *arg);

	static void input_cb(evutil_socket_t fd, short events, void *arg);

	static int i;
};

  

#include "libevent_client.h"
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/event.h>


libevent_client::libevent_client()
{
}


libevent_client::~libevent_client()
{
}

void libevent_client::initial(int port)
{
	m_port = port;
	memset(&m_sin, 0, sizeof(m_sin));
	m_sin.sin_family = AF_INET;
	m_sin.sin_port = htons(m_port);
	//m_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	inet_pton(AF_INET, "192.168.5.115", &m_sin.sin_addr.s_addr);

#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
#endif

	// 创建base
	m_base = event_base_new();

	// 将套接字和base关联起来,得到bufferevent
	m_bev = bufferevent_socket_new(m_base, -1, BEV_OPT_CLOSE_ON_FREE);
	if (!m_bev)
	{
		std::cout << "error , create socket buffer." << std::endl;
		return;
	}
}

void libevent_client::read_cb(struct bufferevent *bev, void *arg)
{
	char buf[1024] = { 0 };

	 //直接从bufferevent将数据读取出来
	bufferevent_read(bev, buf, sizeof(buf));
	int length = strlen(buf);
	if (length)
	{
		std::cout << "client recv msg:" << buf << std::endl;
	}


	// // 从bufferevent将数据读取出来,存放到evbuffer中
	//struct evbuffer *input = bufferevent_get_input(bev);

	//int length = evbuffer_get_length(input);

	//if (length)
	//{
	//	evbuffer_remove(input, buf, sizeof(buf));

	//	std::cout << "client recv msg:" << buf << std::endl;
	//}

	memset(buf, 0, 1024);
	return;
}

void libevent_client::write_cb(struct bufferevent *bev, void *arg)
{
	//// listen client send message. if client not send message will not trigger this callback
	//// if send message not use evbuffer, then bufferevent_get_input can not get the message
	//char buf[1024] = { 0 };

	//struct evbuffer *output = bufferevent_get_output(bev);

	//int length = evbuffer_get_length(output);

	//if (length)
	//{
	//	evbuffer_remove(output, buf, sizeof(buf));

	//	std::cout << "client send msg:" << buf << std::endl;
	//}

	//memset(buf, 0, 1024);

	return;
}

void libevent_client::event_cb(struct bufferevent *bev, short events, void *arg)
{
	if (events & BEV_EVENT_EOF)
	{
		std::cout << "Connection closed." << std::endl;
		bufferevent_free(bev);
	}
	else if (events & BEV_EVENT_ERROR)
	{
		std::cout << "Got an error on the connection." << std::endl;
		bufferevent_free(bev);
	}
	else if (events & BEV_EVENT_CONNECTED)
	{
		std::cout << "Connection server success." << std::endl;
	}
	return;
}

void libevent_client::input_cb(evutil_socket_t fd, short events, void *arg)
{
	// 输入事件加入到未决事件集中后,激活了input_cb,此时event_cb还未被激活
	bufferevent *bev = (bufferevent *)arg;
	char buf[1024] = { 0 };
	if (i > 0 && i < 10)
	{
		//std::cout << "input the message send to server: ";
		//std::cin >> buf;
		memcpy(buf, itoa(i, buf, _MAX_ITOSTR_BASE10_COUNT), 1);
	}
	if (strlen(buf))
	{
		bufferevent_write(bev, buf, strlen(buf) + 1);
	}
	memset(buf, 0, 1024);
	Sleep(1000);
	i++;
	return;
}


void libevent_client::connect_communicate()
{
	// 连接服务端
	int res = bufferevent_socket_connect(m_bev, (struct sockaddr *)&m_sin, sizeof(m_sin));

	if (res != 0)
	{
		std::cout << "connect failed." << std::endl;
		return;
	}

	bufferevent_setcb(m_bev, read_cb, write_cb, event_cb, NULL);

	bufferevent_enable(m_bev, EV_READ | EV_PERSIST);

	m_event = event_new(m_base, bufferevent_getfd(m_bev), EV_WRITE | EV_PERSIST, input_cb, m_bev);

	event_add(m_event, NULL);

	int i = event_base_get_num_events(m_base, EVENT_BASE_COUNT_ADDED);

	event_base_dispatch(m_base);

	event_base_free(m_base);

	event_free(m_event);

	return;
}

  

测试

#include <iostream>
#include "libevent_client.h"
int libevent_client::i = 0;

int main()
{
	libevent_client client;
	client.initial(6000);
	client.connect_communicate(); 
}

  

服务端

#pragma once
#include <event2/util.h>


class libevent_server
{
public:
	libevent_server();
	~libevent_server();


	void initial(int port);

	void creat_bind_accept();


private:
	struct sockaddr_in m_sin;
	int m_port;
	struct event_base *m_base;
	struct evconnlistener *m_listener;

private:
	static void conn_readcb(struct bufferevent *bev, void *user_data);
	static void conn_writecb(struct bufferevent *bev, void *user_data);
	static void conn_eventcb(struct bufferevent *bev, short events, void *user_data);
	static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data);

};

  

#include "libevent_server.h"
#include <iostream>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/event.h>


libevent_server::libevent_server()
{
}


libevent_server::~libevent_server()
{
}

void libevent_server::conn_readcb(struct bufferevent *bev, void *user_data)
{
	char buf[1024] = { 0 };

	//// 直接将数据从bufferevent中读取出来
	//bufferevent_read(bev, buf, sizeof(buf));
	//int length = strlen(buf);
	//if (length)
	//{
	//	std::cout << "server recv msg:" << buf << std::endl;
	//}

	// 将数据从bufferevent存放到evbuffer中
	struct evbuffer *input = bufferevent_get_input(bev);

	int length = evbuffer_get_length(input);

	if (length)
	{
		evbuffer_remove(input, buf, sizeof(buf));

		std::cout << "server recv msg:" << buf << std::endl;

		bufferevent_getfd(bev);

		bufferevent_write(bev, buf, strlen(buf) + 1);

	}
	memset(buf, 0, 1024);
	return;
}

void libevent_server::conn_writecb(struct bufferevent *bev, void *user_data)
{
	// listen server send message. if server not send message will not trigger this callback
	// if send message not use evbuffer, then bufferevent_get_input can not get the message
	char buf[1024] = { 0 };

	struct evbuffer *output = bufferevent_get_output(bev);

	int length = evbuffer_get_length(output);

	if (length)
	{
		evbuffer_copyout(output, buf, sizeof(buf));

		std::cout << "server send msg:" << buf << std::endl;
	}

	evbuffer_free(output);
	memset(buf, 0, 1024);
	return;
}

void libevent_server::conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
	if (events & BEV_EVENT_EOF) 
	{
		std::cout << "Connection closed." << std::endl;
	}
	else if (events & BEV_EVENT_ERROR) 
	{
		std::cout << "Got an error on the connection." << std::endl;
	}
	/* None of the other events can happen here, since we haven't enabled timeouts */
	bufferevent_free(bev);
	return;
}

void libevent_server::listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data)
{
	struct event_base *base = (struct event_base *)user_data;
	struct bufferevent *bev;

	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	if (!bev) 
	{
		std::cout << "Error constructing bufferevent!" << std::endl;
		event_base_loopbreak(base);
		return;
	}
	bufferevent_setcb(bev, conn_readcb, NULL, conn_eventcb, NULL);

	bufferevent_enable(bev, EV_READ | EV_WRITE);

	return;
}

void libevent_server::initial(int port)
{
	m_port = port;
	m_sin = { 0 };
	m_sin.sin_family = AF_INET;
	m_sin.sin_port = htons(m_port);

#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
#endif

	m_base = event_base_new();
	if (!m_base)
	{
		std::cout << "not initial libevent." << std::endl;
		return;
	}
	return;
}


void libevent_server::creat_bind_accept()
{
	// 绑定
	m_listener = evconnlistener_new_bind(m_base, listener_cb, (void *)m_base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
		(struct sockaddr*)&m_sin, sizeof(m_sin));

	// 启动循环监听
	event_base_dispatch(m_base);

	// 释放
	evconnlistener_free(m_listener);
	event_base_free(m_base);
	return;
}

  

测试

#include <iostream>
#include <string>
#include "libevent_server.h"

int main()
{
	libevent_server server;
	server.initial(6000);
	server.creat_bind_accept();
}

  

测试结果

 

posted @ 2020-06-19 11:49  N_zero  阅读(460)  评论(0)    收藏  举报