libevent监控客户端连接并获取连接

43 阅读2分钟

注册服务端接收事件

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <event2/event.h>
#include <event2/util.h>
#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>

#ifdef _WIN32
#else
#include <signal.h>
#endif

void ListenCallback(evutil_socket_t sock, short what, void * arg) {
    std::cout << "accept new connection!" << std::endl;
    if (!(what & EV_READ)) {
        std::cout << "Not Read" << std::endl;
        return;
    }

    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));

    socklen_t size = sizeof(sin);

    evutil_socket_t client_socket = accept(sock, (sockaddr*)&sin, &size);
    if (client_socket <= 0) {
        std::cerr << "accept error" << strerror(errno) << std::endl;
        return;
    }
    char ip[16] = {0};
    evutil_inet_ntop(AF_INET, &sin.sin_addr, ip, sizeof(ip));
    std::cout << "accept new connection from " << ip << std::endl;


}

int main(int argc, char* argv[]) {

    // 端口地址
    int server_port = 8080;

    if (argc > 1) {
        // 从命令行传入指定的端口号
        server_port = atoi(argv[1]);
    }

#ifdef _WIN32
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);
#else
    // 使用断开连接socket,会发出此信号,造成程序退出,因此忽略此信号
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
        return 1;
    }
#endif

    std::cout << "test event server!\n";
    // 创建libevent的上下文,默认是创建base锁
    event_base * base = event_base_new();
    if (base) {
        std::cout << "event_base_new success!" << std::endl; 
    }

    // 创建socket,绑定端口
    evutil_socket_t sock = socket(AF_INET, SOCK_STREAM, 0);

    if (sock <= 0) {
        std::cerr << "socket error" << strerror(errno) << std::endl;
        return -1;
    }

    // 设置地址复用和非阻塞
    evutil_make_socket_nonblocking(sock);
    evutil_make_listen_socket_reuseable(sock);

    // 绑定端口
    sockaddr_in sin;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(server_port);

    int re = ::bind(sock, (sockaddr*)&sin, sizeof(sin));

    if (re != 0) {
        std::cerr << "bind port error" << strerror(errno) << std::endl;
        return -1;
    }

    std::cout << "bind port success!" << std::endl;

    // 监听端口
    listen(sock, 10);

    // 创建监听事件
    // EV_PERSIST持久化,不然只进入一次事件
    // event_self_cbarg() 传递当前创建的event对象
    event* ev = event_new(base, sock, EV_READ | EV_PERSIST | EV_ET , ListenCallback, event_self_cbarg());

    // 开始监听事件
    // 0表示超时事件
    event_add(ev, 0);

    // 事件循环
    // 判断事件是否发生,分发事件到回调函数
    event_base_dispatch(base);

    // 关闭socket
    evutil_closesocket(sock);

    // 清除事件
    event_del(ev);
    event_free(ev);

    // 释放libevent的上下文
    event_base_free(base);


    return 0;
}

编译

Makefile文件

test_event_server:first_libevent.cpp
	g++ $^ -o $@ -levent

clean:
	rm -f test_event_server
	rm -f *.o
make test_event_server

运行

image.png

image.png

image.png