Linux C写一个允许20个客户端接入的聊天室服务端
时间: 2023-09-01 19:10:44 浏览: 128
下面是一个简单的Linux C聊天室服务端代码,支持最多20个客户端连接。它使用了多路复用技术,可以同时监听多个套接字,以便在任何一个套接字准备好读取或写入数据时可以立即处理。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#define MAX_CLIENTS 20
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int server_fd, client_fds[MAX_CLIENTS];
struct sockaddr_in server_addr, client_addr;
fd_set read_fds, write_fds;
int max_fd;
char buffer[BUFFER_SIZE];
// 创建服务器套接字
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 绑定服务器套接字到本地地址和端口
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(8888);
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
// 开始监听连接请求
if (listen(server_fd, MAX_CLIENTS) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 初始化客户端套接字数组
int i;
for (i = 0; i < MAX_CLIENTS; i++) {
client_fds[i] = -1;
}
// 使用多路复用技术监听多个套接字
while (1) {
// 初始化fd_set
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_SET(server_fd, &read_fds);
max_fd = server_fd;
// 将所有有效的客户端套接字加入fd_set
for (i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] != -1) {
FD_SET(client_fds[i], &read_fds);
FD_SET(client_fds[i], &write_fds);
if (client_fds[i] > max_fd) {
max_fd = client_fds[i];
}
}
}
// 监听所有套接字
if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
perror("select");
exit(EXIT_FAILURE);
}
// 处理服务器套接字连接请求
if (FD_ISSET(server_fd, &read_fds)) {
// 接受新的客户端连接请求
socklen_t addr_len = sizeof(client_addr);
int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len);
if (client_fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 将新的客户端套接字加入数组中
for (i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] == -1) {
client_fds[i] = client_fd;
printf("New client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
break;
}
}
}
// 处理客户端套接字的读写事件
for (i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] != -1) {
if (FD_ISSET(client_fds[i], &read_fds)) {
// 读取客户端发送的数据
int n = read(client_fds[i], buffer, BUFFER_SIZE);
if (n < 0) {
perror("read");
exit(EXIT_FAILURE);
} else if (n == 0) {
// 客户端连接关闭
close(client_fds[i]);
client_fds[i] = -1;
printf("Client disconnected: %d\n", client_fds[i]);
} else {
// 将数据广播给所有客户端
int j;
for (j = 0; j < MAX_CLIENTS; j++) {
if (client_fds[j] != -1 && client_fds[j] != client_fds[i]) {
write(client_fds[j], buffer, n);
}
}
}
}
}
}
}
// 关闭服务器套接字
close(server_fd);
return 0;
}
```
这段代码使用了一个长度为20的数组来存储客户端套接字,每当有新的客户端连接时,它会将新的套接字加入数组中。在处理读写事件时,它会遍历所有有效的客户端套接字,并使用select函数来监听所有套接字的读写事件。当有客户端发送数据时,它会将数据广播给所有其他客户端。
阅读全文