多进程实现TCP并发服务器。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define SERVER_PORT 12345 #define BACKLOG 5 #define BUF_SIZE 1024 void handle_client(int client_sockfd) { char recv_buf[BUF_SIZE]; int recv_len; while ((recv_len = recv(client_sockfd, recv_buf, BUF_SIZE - 1, 0)) > 0) { recv_buf[recv_len] = '\0'; printf("Received message from client: %s\n", recv_buf); send(client_sockfd, recv_buf, recv_len, 0); // 回显消息 } close(client_sockfd); exit(0); } int main() { int server_sockfd, client_sockfd; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; pid_t child_pid; // 创建TCP套接字 if ((server_sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 绑定地址和端口 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_sockfd, BACKLOG) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } printf("Server is listening on port %d\n", SERVER_PORT); while (1) { // 接受连接 client_addr_len = sizeof(client_addr); if ((client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) { perror("accept failed"); continue; } // 创建子进程处理客户端请求 if ((child_pid = fork()) < 0) { perror("fork failed"); close(client_sockfd); continue; } if (child_pid == 0) { // 子进程 close(server_sockfd); // 子进程不需要服务器套接字 handle_client(client_sockfd); } else { // 父进程 close(client_sockfd); // 父进程不需要客户端套接字 } } close(server_sockfd); return 0; }
多线程实现TCP并发服务器。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h> #define SERVER_PORT 12345 #define BACKLOG 5 #define BUF_SIZE 1024 void *handle_client(void *arg) { int client_sockfd = *((int *)arg); char recv_buf[BUF_SIZE]; int recv_len; free(arg); // 因为我们已经复制了文件描述符,所以可以释放原始指针 while ((recv_len = recv(client_sockfd, recv_buf, BUF_SIZE - 1, 0)) > 0) { recv_buf[recv_len] = '\0'; printf("Received message from client: %s\n", recv_buf); send(client_sockfd, recv_buf, recv_len, 0); // 回显消息 } close(client_sockfd); pthread_exit(NULL); } int main() { int server_sockfd, *client_sockfd_ptr; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; pthread_t thread_id; // 创建TCP套接字 if ((server_sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 绑定地址和端口 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_sockfd, BACKLOG) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } printf("Server is listening on port %d\n", SERVER_PORT); while (1) { // 接受连接 client_addr_len = sizeof(client_addr); if ((client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) { perror("accept failed"); continue; } // 为每个客户端创建新的线程 if ((client_sockfd_ptr = malloc(sizeof(int))) == NULL) { perror("malloc failed"); close(client_sockfd); continue; } *client_sockfd_ptr = client_sockfd; if (pthread_create(&thread_id, NULL, handle_client, client_sockfd_ptr) != 0) { perror("pthread_create failed"); close(client_sockfd); free(client_sockfd_ptr); continue; } // 分离线程,这样资源可以被回收 pthread_detach(thread_id); } close(server_sockfd); return 0; }