基于libevent的多线程Server实现

最近在学习libevent,写了一些测试的例子,最开始是用共享内存实现的,后来改成了多线程。而且很多细节没有考虑。先存下档,后面再改(不改了)

main.cpp

#include "stdafx.h"
#include<stdio.h>  
#include<string.h>  
#include<errno.h>  

#include<event.h>  
#include<event2/bufferevent.h>  
#include "ThreadPool.h"
#include "event2/thread.h"
#include "EventWork.h"
#include <vector>

void accept_cb(int fd, short events, void* arg);
int tcp_server_init(int port, int listen_num);
int THREAD_NUM = 10;
int g_count = 0;
int last_thread = 0;

EventWork* g_works;

int main(int argc, char** argv)
{
	//加载套接字库  
	WSADATA wsaData;
	int iRet = 0;
	iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iRet != 0)
	{
		return -1;
	}

	if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
	{
		WSACleanup();
		return -1;
	}

	int listener = tcp_server_init(9999, 10000000);
	if (listener == -1)
	{
		return -1;
	}
	evthread_use_windows_threads();
	g_works = new EventWork[THREAD_NUM];
	event_config *base_config = event_config_new();
	event_config_set_flag(base_config, EVENT_BASE_FLAG_STARTUP_IOCP);
	event_config_set_num_cpus_hint(base_config, 4);

	event_base *base = event_base_new_with_config(base_config);

	//listen client connect event
	event *ev_listen = event_new(base, listener, EV_READ | EV_PERSIST, accept_cb, base);
	event_add(ev_listen, nullptr);

	event_base_dispatch(base);
	event_base_free(base);
	ThreadPool::getInstance().realase();
	return 0;
}

void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags)
{
	int tid = (last_thread + 1) % THREAD_NUM;
	EventWork *work = g_works + tid;
	last_thread = tid;

	std::shared_ptr<EventTask> item = std::make_shared<EventTask>();

	item->sfd = sfd;
	item->init_state = init_state;
	item->event_flags = event_flags;

	work->addTask(item);
}

void accept_cb(int fd, short events, void* arg)
{
	evutil_socket_t sockfd;
	sockaddr_in client;
	socklen_t len = sizeof(client);

	sockfd = accept(fd, (sockaddr*)&client, &len);
	evutil_make_socket_nonblocking(sockfd);
	printf("accept a client %d  total %d\n", sockfd, ++g_count);
	dispatch_conn_new(sockfd, conn_new_cmd, EV_READ | EV_PERSIST);
}

int tcp_server_init(int port, int listen_num)
{
	int errno_save;
	evutil_socket_t listener;
	listener = socket(AF_INET, SOCK_STREAM, 0);
	if (listener == -1)
	{
		return -1;
	}

	//允许多次绑定同一地址
	evutil_make_listen_socket_reuseable(listener);

	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = 0;
	sin.sin_port = htons(port);

	do
	{
		if (bind(listener, (sockaddr*)&sin, sizeof(sin)) < 0)
		{
			break;
		}

		if (listen(listener, listen_num) < 0)
		{
			break;
		}

		evutil_make_socket_nonblocking(listener);
		return listener;

	} while (0);

	errno_save = errno;
	evutil_closesocket(listener);
	errno = errno_save;
	return -1;
}

EventWork.h

#ifndef WORKEVENT_H
#define WORKEVENT_H

#include <memory>
#include <thread>
#include <event.h>



enum conn_states 
{
	conn_new_cmd
};

struct EventTask 
{
	int sfd;
	conn_states init_state;
	int event_flags;
};

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

	void addTask(std::shared_ptr<EventTask> task);

	void processTask(evutil_socket_t input_t, short event);


private:
	std::shared_ptr<std::thread> m_ptrWorkThread;

	event_base* m_workBase;
	
};

#endif

EventWork.cpp

#include "stdafx.h"
#include "EventWork.h"
#include <iostream>
#include "event2/thread.h"
#include "ThreadPool.h"



EventWork::EventWork()
{
	m_ptrWorkThread = std::make_shared<std::thread>([this] {
		event_config *base_config = event_config_new();
		event_config_set_flag(base_config, EVENT_BASE_FLAG_STARTUP_IOCP);
		event_config_set_num_cpus_hint(base_config, 4);

		m_workBase = event_base_new_with_config(base_config);
		event *notifyEvent = event_new(m_workBase, -1, EV_PERSIST | EV_READ, nullptr, this);
		timeval *tv = new timeval;
		tv->tv_sec = 24 * 60 * 60;
		tv->tv_usec = 0;
		event_add(notifyEvent, tv);

		event_base_dispatch(m_workBase);
	});
	
}


EventWork::~EventWork()
{
}

void EventWork::addTask(std::shared_ptr<EventTask> task)
{
	ThreadPool::getInstance().putTask([task, this] {
		if (task)
		{
			bufferevent* bev = bufferevent_socket_new(m_workBase, task->sfd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
			bufferevent_setcb(bev,
				[](bufferevent* bev, void * arg) {
				char msg[1024];
				size_t len = bufferevent_read(bev, msg, sizeof(msg));

				//msg[4095] = '\0';
				//printf("recv the client msg: %s", msg);
				char reply[] = "i have recvieced the msg";
				bufferevent_write(bev, reply, strlen(reply));
			},
				nullptr,
				[](bufferevent* bev, short e, void* arg) {
				if (e & BEV_EVENT_EOF)
				{
					printf("connect closed \n");
				}
				else if (e & BEV_EVENT_ERROR)
				{
					printf("connect error \n");
				}
				printf("close a client\n");
				bufferevent_free(bev);
			},
				nullptr);
			bufferevent_enable(bev, EV_READ | EV_PERSIST);
		}
	});
}

void EventWork::processTask(evutil_socket_t input_t, short event)
{

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值