2021-11-19 00:37:35 +08:00
|
|
|
#include "tcp_server_libevent.h"
|
2021-12-30 11:29:04 +08:00
|
|
|
extern "C" {
|
|
|
|
#include "event2/bufferevent.h"
|
|
|
|
#include "event2/buffer.h"
|
|
|
|
#include "event2/listener.h"
|
|
|
|
#include "event2/util.h"
|
|
|
|
#include "event2/event.h"
|
|
|
|
#include "event2/thread.h"
|
|
|
|
};
|
2021-11-19 00:37:35 +08:00
|
|
|
|
2022-01-13 01:37:24 +08:00
|
|
|
void defaultConnRead(char* p, uint32_t len) {
|
|
|
|
std::cout << p;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
class ServerCallbacks {
|
|
|
|
public:
|
2022-02-23 00:13:30 +08:00
|
|
|
static void cb_listener(struct evconnlistener* listener,
|
|
|
|
evutil_socket_t fd, struct sockaddr* addr, int len, void* ptr);
|
2021-12-30 11:29:04 +08:00
|
|
|
static void server_run(TcpServerLibevent* p);
|
|
|
|
};
|
|
|
|
|
2022-02-23 00:13:30 +08:00
|
|
|
ConnectionLibevent::ConnectionLibevent(TcpServerLibevent* p,
|
|
|
|
struct bufferevent* ev, uint32_t fd, struct sockaddr_in* p1) :
|
2021-12-30 11:29:04 +08:00
|
|
|
m_parent_server(nullptr),
|
|
|
|
m_event(nullptr),
|
|
|
|
m_fd(-1),
|
2022-01-13 01:37:24 +08:00
|
|
|
m_addr(nullptr),
|
|
|
|
m_recv_handle(defaultConnRead)
|
2021-11-19 00:37:35 +08:00
|
|
|
{
|
|
|
|
m_parent_server = p;
|
|
|
|
m_event = ev;
|
|
|
|
m_fd = fd;
|
|
|
|
m_addr = p1;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2022-02-23 00:13:30 +08:00
|
|
|
ConnectionLibevent::ConnectionLibevent(struct bufferevent* ev,
|
|
|
|
uint32_t fd, struct sockaddr_in* p1) :
|
2021-12-30 11:29:04 +08:00
|
|
|
m_parent_server(nullptr),
|
|
|
|
m_event(nullptr),
|
|
|
|
m_fd(-1),
|
|
|
|
m_addr(nullptr)
|
2021-11-19 00:37:35 +08:00
|
|
|
{
|
|
|
|
m_event = ev;
|
|
|
|
m_fd = fd;
|
|
|
|
m_addr = p1;
|
2022-01-05 01:31:16 +08:00
|
|
|
std::cout << "\r\n " << m_addr << " ConnectionLibevent " << inet_ntoa(m_addr->sin_addr) << std::endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2022-01-08 00:23:09 +08:00
|
|
|
void defaultConnAccept(ConnectionLibevent*p1) {
|
|
|
|
std::cout << "defaultConnAccept " << p1->Close();
|
|
|
|
|
|
|
|
return ;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2022-01-05 01:31:16 +08:00
|
|
|
void defaultConnClose(ConnectionLibevent*p) {
|
|
|
|
std::cout << "defaultConnClose close connection " << p->IpAddress() << p->SocketFd()<<std::endl;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
int ConnectionLibevent::OnRecv(char* p, uint32_t len) {
|
|
|
|
std::cout << "OnRecv " << p << std::endl;
|
2022-01-13 01:37:24 +08:00
|
|
|
if (m_recv_handle != nullptr) {
|
|
|
|
(m_recv_handle)(p, len);
|
|
|
|
}
|
2021-11-19 00:37:35 +08:00
|
|
|
m_bytes_recv += len;
|
|
|
|
return 0;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
|
|
|
int ConnectionLibevent::OnClose() {
|
|
|
|
std::cout << "close " << this->m_fd << " " << this->IpAddress() << std::endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
int ConnectionLibevent::OnWrite() {
|
2021-11-19 00:37:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
|
|
|
int ConnectionLibevent::WriteData(const char* p, uint16_t len) {
|
|
|
|
if (nullptr == p) {
|
2021-11-19 00:37:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
return bufferevent_write(this->m_event, p, len);
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
uint32_t ConnectionLibevent::SocketFd() {
|
2021-11-19 00:37:35 +08:00
|
|
|
return m_fd;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
|
|
|
int ConnectionLibevent::Close() {
|
|
|
|
if (m_event != nullptr) {
|
|
|
|
bufferevent_free(this->m_event);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2022-01-13 01:37:24 +08:00
|
|
|
int ConnectionLibevent::SetRecvHandler(OnRecvHandle p) {
|
|
|
|
if (nullptr == p)
|
|
|
|
return -1;
|
|
|
|
this->m_recv_handle = p;
|
|
|
|
return 0;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
|
|
|
int ConnectionLibevent::SetServer(TcpServerLibevent* p) {
|
|
|
|
if (nullptr != p) {
|
2021-11-19 00:37:35 +08:00
|
|
|
this->m_parent_server = p;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
string ConnectionLibevent::IpAddress() {
|
2022-01-05 01:31:16 +08:00
|
|
|
|
|
|
|
std::cout<< m_addr << " IpAddress: " << inet_ntoa(m_addr->sin_addr)<<"port " << htons(m_addr->sin_port) << std::endl;
|
|
|
|
return string(inet_ntoa(this->m_addr->sin_addr));
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
TcpServerLibevent* ConnectionLibevent::Server() {
|
2021-11-19 00:37:35 +08:00
|
|
|
return m_parent_server;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
void read_cb(struct bufferevent* bev, void* arg)
|
2021-11-19 00:37:35 +08:00
|
|
|
{
|
2021-12-30 11:29:04 +08:00
|
|
|
char buf[1024] = { 0 };
|
2022-01-05 01:31:16 +08:00
|
|
|
ConnectionLibevent* conn = static_cast<ConnectionLibevent*> (arg);
|
2021-11-19 00:37:35 +08:00
|
|
|
bufferevent_read(bev, buf, sizeof(buf));
|
2022-01-05 01:31:16 +08:00
|
|
|
cout << "client " << conn->IpAddress().c_str() << " say:" << buf << endl;
|
2021-12-30 11:29:04 +08:00
|
|
|
conn->OnRecv(buf, sizeof(buf));
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
void write_cb(struct bufferevent* bev, void* arg)
|
2021-11-19 00:37:35 +08:00
|
|
|
{
|
|
|
|
ConnectionLibevent* conn = (ConnectionLibevent*)arg;
|
2022-01-05 01:31:16 +08:00
|
|
|
std::cout << "connection " << conn->IpAddress() << " sended data " << std::endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2022-01-05 01:31:16 +08:00
|
|
|
void event_cb(struct bufferevent* bev, short events, void* arg)
|
2021-11-19 00:37:35 +08:00
|
|
|
{
|
2021-12-30 11:29:04 +08:00
|
|
|
ConnectionLibevent* conn = (ConnectionLibevent*)(arg);
|
|
|
|
TcpServerLibevent* server = conn->Server();
|
|
|
|
if (events & BEV_EVENT_EOF)
|
|
|
|
{
|
|
|
|
conn->OnClose();
|
|
|
|
cout << "connection closed BEV_EVENT_EOF: " << conn->IpAddress() << " " << conn->SocketFd() << endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
bufferevent_free(bev);
|
|
|
|
server->RemoveConnection(conn->SocketFd());
|
2021-12-30 11:29:04 +08:00
|
|
|
}
|
|
|
|
else if (events & BEV_EVENT_ERROR)
|
|
|
|
{
|
|
|
|
cout << "BEV_EVENT_ERROR !" << endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
conn->OnClose();
|
2021-12-30 11:29:04 +08:00
|
|
|
cout << "connection closed: " << conn->IpAddress() << " " << conn->SocketFd() << endl;
|
2021-11-19 00:37:35 +08:00
|
|
|
bufferevent_free(bev);
|
|
|
|
server->RemoveConnection(conn->SocketFd());
|
2021-12-30 11:29:04 +08:00
|
|
|
}
|
2021-12-30 16:56:16 +08:00
|
|
|
|
|
|
|
//delete conn;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
|
2022-01-05 01:31:16 +08:00
|
|
|
void ServerCallbacks::cb_listener(struct evconnlistener* listener, evutil_socket_t fd,
|
|
|
|
struct sockaddr* addr, int len, void* ptr)
|
2021-12-30 11:29:04 +08:00
|
|
|
{
|
2022-01-05 01:31:16 +08:00
|
|
|
struct sockaddr_in* client = new(struct sockaddr_in);
|
|
|
|
memcpy(client, addr, sizeof(struct sockaddr));
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
cout << "connect new client: " << inet_ntoa(client->sin_addr)
|
2022-01-05 01:31:16 +08:00
|
|
|
<< " port: " << " ::" << ntohs(client->sin_port) << endl;
|
2021-12-30 11:29:04 +08:00
|
|
|
TcpServerLibevent* server = (TcpServerLibevent*)ptr;
|
|
|
|
if (server != nullptr) {
|
|
|
|
std::cout << "null 2" << std::endl;
|
|
|
|
struct bufferevent* bev = nullptr;
|
2021-11-19 00:37:35 +08:00
|
|
|
bev = bufferevent_socket_new(server->m_event_base, fd, BEV_OPT_CLOSE_ON_FREE);
|
2021-12-30 11:29:04 +08:00
|
|
|
std::cout << "null 4" << bev << std::endl;
|
2022-01-06 00:31:24 +08:00
|
|
|
// 这是一个bad design,
|
2022-01-08 00:23:09 +08:00
|
|
|
ConnectionLibevent* conn = new ConnectionLibevent(bev, ntohs(client->sin_port), client);
|
2021-11-19 00:37:35 +08:00
|
|
|
conn->SetServer(server);
|
2021-12-30 11:29:04 +08:00
|
|
|
server->AddConnection(ntohs(client->sin_port), conn);
|
|
|
|
bufferevent_setcb(bev, read_cb,
|
|
|
|
write_cb,
|
|
|
|
event_cb,
|
|
|
|
conn);
|
2022-01-08 00:23:09 +08:00
|
|
|
server->m_handle_accept(conn);
|
2021-12-30 11:29:04 +08:00
|
|
|
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
std::cout << "null 1" << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int test_tcp_server()
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
WORD wVersionRequested;
|
|
|
|
WSADATA wsaData;
|
|
|
|
wVersionRequested = MAKEWORD(2, 2);
|
|
|
|
(void)WSAStartup(wVersionRequested, &wsaData);
|
|
|
|
#endif
|
|
|
|
// init server
|
|
|
|
struct sockaddr_in serv;
|
2021-11-19 00:37:35 +08:00
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
memset(&serv, 0, sizeof(serv));
|
|
|
|
serv.sin_family = AF_INET;
|
|
|
|
serv.sin_port = htons(8888);
|
|
|
|
serv.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
|
|
|
|
struct event_base* base;
|
|
|
|
base = event_base_new();
|
|
|
|
|
|
|
|
struct evconnlistener* listener;
|
|
|
|
listener = evconnlistener_new_bind(base,
|
|
|
|
&ServerCallbacks::cb_listener,
|
|
|
|
base,
|
|
|
|
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
|
|
|
|
30000,
|
|
|
|
(struct sockaddr*)&serv,
|
|
|
|
sizeof(serv));
|
|
|
|
|
|
|
|
if (NULL != listener) {
|
|
|
|
event_base_dispatch(base);
|
|
|
|
evconnlistener_free(listener);
|
|
|
|
event_base_free(base);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return -1;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
void ServerCallbacks::server_run(TcpServerLibevent* p) {
|
|
|
|
if (nullptr != p) {
|
|
|
|
if (p->m_status == TcpServerLibevent::STOP) {
|
|
|
|
p->m_status = TcpServerLibevent::RUNNING;
|
2021-12-30 16:56:16 +08:00
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
event_base_dispatch(p->m_event_base);
|
2021-12-30 16:56:16 +08:00
|
|
|
if(!p->m_event_listener)
|
|
|
|
evconnlistener_free(p->m_event_listener);
|
2021-12-30 11:29:04 +08:00
|
|
|
event_base_free(p->m_event_base);
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
2021-12-30 11:29:04 +08:00
|
|
|
* @description:
|
2021-11-19 00:37:35 +08:00
|
|
|
* @param {*}
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2021-12-30 11:29:04 +08:00
|
|
|
TcpServerLibevent::SERVER_STATUS TcpServerLibevent::Status() {
|
2021-11-19 00:37:35 +08:00
|
|
|
return m_status;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
|
|
|
int TcpServerLibevent::AddConnection(uint32_t fd, ConnectionLibevent* p) {
|
|
|
|
if (m_map_client.find(fd) == m_map_client.end()) {
|
|
|
|
if (nullptr != p)
|
2021-11-19 00:37:35 +08:00
|
|
|
m_map_client[fd] = p;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
int TcpServerLibevent::RemoveConnection(uint32_t fd) {
|
|
|
|
if (m_map_client.find(fd) != m_map_client.end()) {
|
|
|
|
auto pClient = m_map_client[fd];
|
2021-11-19 00:37:35 +08:00
|
|
|
m_map_client.erase(fd);
|
2022-01-08 00:23:09 +08:00
|
|
|
this->m_handle_disconnect(pClient);
|
2021-12-30 11:29:04 +08:00
|
|
|
delete pClient;
|
2021-11-19 00:37:35 +08:00
|
|
|
return 0;
|
2021-12-30 11:29:04 +08:00
|
|
|
}
|
|
|
|
else {
|
2021-11-19 00:37:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2021-12-31 15:35:46 +08:00
|
|
|
|
|
|
|
int TcpServerLibevent::ConnectionCount() {
|
|
|
|
return m_map_client.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
int TcpServerLibevent::SetNewConnectionHandle(OnAccept p) {
|
2021-11-19 00:37:35 +08:00
|
|
|
m_handle_accept = p;
|
|
|
|
return 0;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2022-01-06 00:31:24 +08:00
|
|
|
|
|
|
|
int TcpServerLibevent::SetConnectionLeaveHandle(OnDisconnect p) {
|
|
|
|
m_handle_disconnect = p;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-01-13 01:37:24 +08:00
|
|
|
|
|
|
|
|
2021-11-19 00:37:35 +08:00
|
|
|
/**
|
2021-12-30 11:29:04 +08:00
|
|
|
* @description:
|
|
|
|
* @param {int} ports
|
2021-11-19 00:37:35 +08:00
|
|
|
* @param {string} bindip
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2021-12-30 11:29:04 +08:00
|
|
|
TcpServerLibevent::TcpServerLibevent(int port, string bindip) :
|
2021-11-19 00:37:35 +08:00
|
|
|
m_thread(nullptr),
|
|
|
|
m_event_base(nullptr),
|
|
|
|
m_event_listener(nullptr)
|
|
|
|
{
|
|
|
|
m_handle_accept = defaultConnAccept;
|
2022-01-05 01:31:16 +08:00
|
|
|
m_handle_disconnect = defaultConnClose;
|
2021-11-19 00:37:35 +08:00
|
|
|
m_backlog = 10000;
|
|
|
|
this->m_bind_ip = bindip;
|
|
|
|
this->m_port = port;
|
2021-12-30 11:29:04 +08:00
|
|
|
|
2021-11-19 00:37:35 +08:00
|
|
|
memset(&m_server_addr, 0, sizeof(m_server_addr));
|
|
|
|
m_server_addr.sin_family = AF_INET;
|
|
|
|
m_server_addr.sin_port = htons(port);
|
|
|
|
m_server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
|
|
|
|
// 创建 event_base
|
|
|
|
m_event_base = event_base_new();
|
2021-12-30 11:29:04 +08:00
|
|
|
if (NULL == m_event_base) {
|
2021-11-19 00:37:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_event_listener = evconnlistener_new_bind(m_event_base,
|
2021-12-30 11:29:04 +08:00
|
|
|
&ServerCallbacks::cb_listener,
|
2021-11-19 00:37:35 +08:00
|
|
|
this,
|
2021-12-30 11:29:04 +08:00
|
|
|
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
|
2021-11-19 00:37:35 +08:00
|
|
|
m_backlog,
|
|
|
|
(struct sockaddr*)&m_server_addr,
|
|
|
|
sizeof(m_server_addr));
|
2021-12-30 16:56:16 +08:00
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
if (NULL == m_event_listener)
|
|
|
|
{
|
2021-11-19 00:37:35 +08:00
|
|
|
m_status = FAIL;
|
|
|
|
}
|
|
|
|
m_status = STOP;
|
|
|
|
}
|
2022-01-05 01:31:16 +08:00
|
|
|
|
2021-11-19 00:37:35 +08:00
|
|
|
/**
|
|
|
|
* @description: start server synchronous
|
|
|
|
* @param {*}
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2021-12-30 11:29:04 +08:00
|
|
|
int TcpServerLibevent::StartServerAndRunSync() {
|
|
|
|
if (m_status == STOP) {
|
2021-11-19 00:37:35 +08:00
|
|
|
m_status = RUNNING;
|
2021-12-30 11:29:04 +08:00
|
|
|
event_base_dispatch(m_event_base);
|
|
|
|
evconnlistener_free(m_event_listener);
|
2021-11-19 00:37:35 +08:00
|
|
|
event_base_free(m_event_base);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @description: start server asynchronous
|
|
|
|
* @param {*}
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2021-12-30 11:29:04 +08:00
|
|
|
int TcpServerLibevent::StartServerAsync() {
|
|
|
|
if (m_status == STOP) {
|
2021-11-19 00:37:35 +08:00
|
|
|
#ifdef WIN32
|
|
|
|
evthread_use_windows_threads();
|
|
|
|
#endif
|
|
|
|
#ifdef linux
|
|
|
|
evthread_use_pthreads();
|
|
|
|
#endif
|
2021-12-30 11:29:04 +08:00
|
|
|
m_thread = new thread(ServerCallbacks::server_run, this);
|
2021-11-19 00:37:35 +08:00
|
|
|
m_thread->detach();
|
|
|
|
return 0;
|
|
|
|
}
|
2021-12-30 11:29:04 +08:00
|
|
|
return -1;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
|
|
|
|
2021-12-30 11:29:04 +08:00
|
|
|
TcpServerLibevent::~TcpServerLibevent() {
|
|
|
|
if (this->m_status == RUNNING) {
|
2021-11-19 00:37:35 +08:00
|
|
|
m_thread->detach();
|
2021-12-30 11:29:04 +08:00
|
|
|
event_base_loopbreak(m_event_base);
|
|
|
|
this->m_status = STOP;
|
2021-11-19 00:37:35 +08:00
|
|
|
}
|
2022-01-06 00:31:24 +08:00
|
|
|
|
2021-12-30 16:56:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t TcpServerLibevent::SocketFd()
|
|
|
|
{
|
|
|
|
return mSocketFD;
|
|
|
|
}
|