#include #include #include #include #include #include #include #include #include #define PORT 8080 #define MAX_EVENTS 64 #define BUFFER_SIZE 1024 void set_nonblocking(int32_t fd) { int32_t flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } int32_t main(void) { int32_t server_fd = socket(AF_INET, SOCK_STREAM, 0); int32_t opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in address = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(PORT) }; bind(server_fd, (struct sockaddr *)&address, sizeof(address)); listen(server_fd, SOMAXCONN); set_nonblocking(server_fd); printf("server listening on port %d...\n", PORT); int32_t epoll_fd = epoll_create1(0); if (epoll_fd < 0) { perror("epoll_create1 failed"); exit(EXIT_FAILURE); } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = server_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) < 0) { perror("epoll_ctl: server_fd failed"); exit(EXIT_FAILURE); } struct epoll_event events[MAX_EVENTS]; char buffer[BUFFER_SIZE]; while (1) { int32_t nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds < 0) { perror("epoll_wait failed"); break; } for (int32_t i = 0; i < nfds; i++) { if (events[i].data.fd == server_fd) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int32_t client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd < 0) { perror("accept failed"); continue; } printf("connection accepted (client fd: %d)\n", client_fd); set_nonblocking(client_fd); ev.events = EPOLLIN | EPOLLET; ev.data.fd = client_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) < 0) { perror("epoll_ctl: client_fd failed"); close(client_fd); } } else { int32_t client_fd = events[i].data.fd; while (1) { ssize_t bytes_read = read(client_fd, buffer, sizeof(buffer)); if (bytes_read > 0) { write(client_fd, buffer, bytes_read); } else if (bytes_read == 0) { printf("client on fd %d closed connection.\n", client_fd); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL); close(client_fd); break; } else { if (errno == EAGAIN || errno == EWOULDBLOCK) { break; } perror("read error"); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL); close(client_fd); break; } } } } } close(epoll_fd); close(server_fd); return 0; }