使用C语言实现一个服务器对多个客户端
主要技术除了网络编程几个函数的使用外,还用到了线程,实现方式是一个客户端对应一个新的线程
Server:
#include <pthread.h> // 包含线程库的头文件 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h>void* handle_client(void* arg) { int client_fd = *(int*)arg; // 从参数中获取客户端套接字文件描述符 char readBuf[128]; char *writeBuf = "I get you!";
while (1) { sleep(2);//很重要,防止服务器一直连接同一个客户端 // 循环读取客户端发送的每条消息 memset(readBuf, 0, sizeof(readBuf)); int n_read = read(client_fd, readBuf, sizeof(readBuf)); if (n_read > 0) { // 正常接收到消息 printf("get message from client: %s\n", readBuf); } else if (n_read == 0) { // 客户端关闭连接 printf("Client disconnected.\n"); break; } else { // 读取失败 perror("read"); break; }
// 发送消息回客户端 if (write(client_fd, writeBuf, sizeof(writeBuf)) == -1) { perror("write"); break; } }
close(client_fd); // 关闭客户端套接字 pthread_exit(NULL); // 退出线程 }
int main() { int s_fd, c_fd; struct sockaddr_in s_addr, c_addr; socklen_t len; char readBuf[128]; char *writeBuf = "I get you!"; // 1. 创建socket网络套接字 s_fd = socket(AF_INET, SOCK_STREAM, 0); if (s_fd == -1) { perror("socket"); exit(-1); }
// 2. 绑定本地IP地址和端口号到socket网络套接字上 memset(&s_addr, 0, sizeof(struct sockaddr_in)); s_addr.sin_family = AF_INET; s_addr.sin_port = htons(8421); inet_aton("192.168.190.141", &s_addr.sin_addr); if (bind(s_fd, (struct sockaddr*)&s_addr, sizeof(struct sockaddr_in)) == -1) { perror("bind"); exit(-1); }
// 3. 将socket套接字变为监听套接字,准备接受客户端的连接 if (listen(s_fd, 10) == -1) { perror("listen"); exit(-1); }
// 4. 服务器阻塞等待客户端的连接 len = sizeof(struct sockaddr_in); // 服务器主循环 while (1) { // 4. 服务器阻塞等待客户端的连接 len = sizeof(struct sockaddr_in); c_fd = accept(s_fd, (struct sockaddr*)&c_addr, &len); if (c_fd == -1) { perror("accept"); exit(-1); } printf("Success Connected\n"); printf("get connect :%s\n", inet_ntoa(c_addr.sin_addr));
// 创建新线程处理客户端连接 pthread_t thread_id; if (pthread_create(&thread_id, NULL, handle_client, &c_fd) != 0) { perror("pthread_create"); close(c_fd); // 如果线程创建失败,关闭客户端套接字 exit(-1); } // 销毁线程,这里不销毁,让线程自然结束 pthread_detach(thread_id); }
close(s_fd); // 关闭服务器套接字 return 0; }
Client:
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h>int main() { int c_fd; struct sockaddr_in s_addr; char msg[128], readBuf[128];
// 1. 创建socket网络套接字 c_fd = socket(AF_INET, SOCK_STREAM, 0); if (c_fd == -1) { perror("socket"); exit(-1); }
// 2. 连接服务端 memset(&s_addr, 0, sizeof(struct sockaddr_in)); s_addr.sin_family = AF_INET; inet_aton("192.168.190.141", &s_addr.sin_addr); s_addr.sin_port = htons(8421);
if (connect(c_fd, (struct sockaddr*)&s_addr, sizeof(struct sockaddr_in)) == -1) { perror("connect"); exit(-1); } printf("Connected to server at %s\n", inet_ntoa(s_addr.sin_addr));
// 3. 发送信息到服务端 while (scanf("%127s", msg) == 1) { // 使用%127s防止缓冲区溢出 if (write(c_fd, msg, strlen(msg)) == -1) { perror("write"); break; }
// 4. 读取服务端发来的消息 int n_read = read(c_fd, readBuf, sizeof(readBuf)); if (n_read > 0) { readBuf[n_read] = '\0'; // 确保字符串以null字符结尾 printf("Received message: %s\n", readBuf); } else if (n_read == -1) { perror("read"); break; } else if (n_read == 0) { printf("Server closed the connection.\n"); break; } }
close(c_fd); return 0; } 标签:通讯,addr,read,编程,C语言,fd,readBuf,include,客户端 From: https://www.cnblogs.com/trc258/p/18305460