[转]Linux TCP server系列-集合

Linux C语言中,TCP服务器通常使用`select()`函数来管理多个套接字连接,因为`select()`可以高效地阻塞和唤醒进程,适用于非阻塞I/O。下面是一个简单的TCP服务器示例,包括了详细的注释: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/time.h> #include <sys/select.h> #define MAX_CLIENTS 5 #define BUFFER_SIZE 1024 // 创建一个新的socket int create_socket(int family, int type, int protocol) { int sock = socket(family, type, protocol); if (sock == -1) { perror("Error creating socket"); exit(EXIT_FAILURE); } return sock; } // 绑定并监听socket void bind_and_listen(int sock, const char *ip, int port) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); // 将port换为网络字节序 inet_pton(AF_INET, ip, &addr.sin_addr); if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("Error binding to address"); exit(EXIT_FAILURE); } listen(sock, MAX_CLIENTS); printf("Server listening on %s:%d...\n", ip, port); } // 接受新的客户端连接 int accept_new_client(int server_sock) { struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int new_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len); if (new_sock == -1) { perror("Error accepting client connection"); exit(EXIT_FAILURE); } printf("Accepted connection from %s\n", inet_ntoa(client_addr.sin_addr)); return new_sock; } // 主循环处理客户端请求 void handle_client(int client_sock) { char buffer[BUFFER_SIZE]; ssize_t bytes_received; while ((bytes_received = recv(client_sock, buffer, BUFFER_SIZE, 0)) > 0) { buffer[bytes_received] = '\0'; // 结束字符串 printf("Received message from client: %s\n", buffer); // 发送响应给客户端(这里仅简单打印信息) send(client_sock, "Message received!", strlen("Message received!"), 0); } if (bytes_received == -1) { perror("Error receiving data from client"); } else if (bytes_received == 0) { // 客户端断开连接 printf("Client disconnected.\n"); close(client_sock); } } int main() { int server_sock = create_socket(AF_INET, SOCK_STREAM, 0); // 绑定和监听 struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 静态IP地址0.0.0.0表示所有网络接口 server_addr.sin_port = htons(8080); bind_and_listen(server_sock, inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port)); fd_set fds; // 用于存储文件描述符集合 FD_ZERO(&fds); // 清空描述符集合 FD_SET(server_sock, &fds); // 添加服务器套接字到集合 struct timeval timeout; timeout.tv_sec = 10; // 设置超时时间,10秒 timeout.tv_usec = 0; while (true) { int max_fd = server_sock; select(max_fd + 1, &fds, NULL, NULL, &timeout); // 等待活动 if (FD_ISSET(server_sock, &fds)) { // 新的连接或已存在的连接有数据可读 int new_client_sock = accept_new_client(server_sock); if (new_client_sock != -1) { FD_SET(new_client_sock, &fds); // 添加新连接到描述符集合 max_fd = new_client_sock; } } else { break; // 没有任何活动,退出循环 } for (int i = 0; i <= max_fd; ++i) { if (FD_ISSET(i, &fds)) { handle_client(i); } } } close(server_sock); printf("Server stopped.\n"); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值