linux多路复用例子
时间: 2023-05-22 07:01:17 浏览: 48
一个常见的 Linux 多路复用例子是使用 select 函数来同时监听多个文件描述符的可读事件。以下是一个简单的示例代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAX_CLIENTS 10
int main(int argc, char *argv[]) {
int server_fd, client_fds[MAX_CLIENTS], max_fd, i, j, activity, valread, sd;
struct sockaddr_in address;
char buffer[1024] = {0};
fd_set readfds;
// 创建服务器 socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置服务器地址和端口
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// 绑定服务器 socket
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听服务器 socket
if (listen(server_fd, 3) < 0) {
perror("listen failed");
exit(EXIT_FAILURE);
}
// 初始化客户端 socket 数组
for (i = 0; i < MAX_CLIENTS; i++) {
client_fds[i] = 0;
}
// 主循环
while (1) {
// 清空文件描述符集合
FD_ZERO(&readfds);
// 将服务器 socket 加入文件描述符集合
FD_SET(server_fd, &readfds);
max_fd = server_fd;
// 将所有已连接的客户端 socket 加入文件描述符集合
for (i = 0; i < MAX_CLIENTS; i++) {
sd = client_fds[i];
// 如果客户端 socket 有效,则加入文件描述符集合
if (sd > 0) {
FD_SET(sd, &readfds);
}
// 更新最大文件描述符
if (sd > max_fd) {
max_fd = sd;
}
}
// 等待文件描述符集合中的任意一个文件描述符变为可读
activity = select(max_fd + 1, &readfds, NULL, NULL, NULL);
if ((activity < 0) && (errno != EINTR)) {
perror("select failed");
}
// 如果服务器 socket 变为可读,则表示有新的客户端连接请求
if (FD_ISSET(server_fd, &readfds)) {
int new_socket;
// 接受新的客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
// 将新的客户端 socket 加入客户端 socket 数组
for (i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] == 0) {
client_fds[i] = new_socket;
break;
}
}
}
// 处理所有已连接的客户端 socket
for (i = 0; i < MAX_CLIENTS; i++) {
sd = client_fds[i];
// 如果客户端 socket 变为可读,则读取数据并回复
if (FD_ISSET(sd, &readfds)) {
if ((valread = read(sd, buffer, 1024)) == 0) {
// 客户端关闭连接
close(sd);
client_fds[i] = 0;
} else {
// 回复客户端
send(sd, buffer, strlen(buffer), 0);
}
}
}
}
return 0;
}
```
这个例子使用 select 函数同时监听服务器 socket 和所有已连接的客户端 socket,当有新的客户端连接请求时,将其加入客户端 socket 数组中;当有客户端 socket 变为可读时,读取数据并回复。这样可以实现一个简单的多客户端聊天室。