// 头文件 #include #include #include #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <fcntl.h> #include <errno.h> #include #include #include <event.h>

// 定义最大事件数量和缓冲区大小 #define MAX_EVENTS 1024 #define BUF_SIZE 1024

// 函数声明 void on_accept(int, short, void*); void on_read(int, short, void*);

int main(int argc, char** argv) { // 检查参数个数是否正确 if (argc < 2) { std::cerr << 'usage: ' << argv[0] << ' ' << std::endl; return EXIT_FAILURE; } // 创建socket int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror('socket'); return EXIT_FAILURE; } // 设置SO_REUSEADDR选项以允许端口复用 int reuse = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { // 这里使用了SO_REUSEADDR选项来允许端口复用,这样可以在服务器重启时更快地重新绑定端口。然后使用bind函数将socket绑定到指定的端口,再使用listen函数将socket设置为监听状态。 perror('setsockopt'); return EXIT_FAILURE; } // 填充地址结构体 struct sockaddr_in addr; std::memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(std::atoi(argv[1])); addr.sin_addr.s_addr = INADDR_ANY; // 将socket绑定到指定端口 if (bind(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1) { perror('bind'); return EXIT_FAILURE; } // 将socket设置为监听状态 if (listen(sockfd, SOMAXCONN) == -1) { perror('listen'); return EXIT_FAILURE; } // 输出监听信息 std::cout << 'listening on port ' << argv[1] << std::endl; // 将socket设置为非阻塞模式 int flags = fcntl(sockfd, F_GETFL, 0); if (flags == -1) { perror('fcntl'); return EXIT_FAILURE; } if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) { perror('fcntl'); return EXIT_FAILURE; } // 创建event_base struct event_base* base = event_base_new(); if (!base) { perror('event_base_new'); return EXIT_FAILURE; } // 创建event,并将其添加到event_base中 struct event* ev_accept = event_new(base, sockfd, EV_READ | EV_PERSIST, on_accept, base); if (!ev_accept) { perror('event_new'); return EXIT_FAILURE; } if (event_add(ev_accept, nullptr) == -1) { perror('event_add'); return EXIT_FAILURE; } // 启动事件循环 event_base_dispatch(base); // 释放event_base event_base_free(base); return EXIT_SUCCESS; }

// 连接事件回调函数 void on_accept(int sockfd, short ev, void* arg) { // 获取event_base struct event_base* base = static_cast<event_base*>(arg); assert(base); // 接受新连接 struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int connfd = accept(sockfd, reinterpret_cast<struct sockaddr*>(&addr), &addrlen); if (connfd == -1) { perror('accept'); return; } // 将连接设置为非阻塞模式 int flags = fcntl(connfd, F_GETFL, 0); if (flags == -1) { perror('fcntl'); return; } if (fcntl(connfd, F_SETFL, flags | O_NONBLOCK) == -1) { perror('fcntl'); return; } // 输出连接信息 std::cout << 'new connection from ' << inet_ntoa(addr.sin_addr) << ':' << ntohs(addr.sin_port) << std::endl; // 创建event,并将其添加到event_base中 struct event* ev_read = event_new(base, connfd, EV_READ | EV_PERSIST, on_read, nullptr); if (!ev_read) { perror('event_new'); return; } if (event_add(ev_read, nullptr) == -1) { perror('event_add'); return; } }

// 读事件回调函数 void on_read(int connfd, short ev, void* arg) { // 定义缓冲区 char buf[BUF_SIZE]; // 接收数据 int n = recv(connfd, buf, sizeof(buf), 0); if (n == -1) { if (errno != EAGAIN && errno != EWOULDBLOCK) { perror('recv'); } return; } // 检查连接是否关闭 if (n == 0) { std::cout << 'connection closed by remote host' << std::endl; close(connfd); return; } // 添加字符串结束符 buf[n] = '\0'; // 输出接收到的数据 std::cout << 'received ' << n << ' bytes: ' << buf << std::endl; // 发送数据 if (send(connfd, buf, n, 0) == -1) { perror('send'); return; } }


原文地址: https://www.cveoy.top/t/topic/nl5P 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录