C++ 多路复用技术DEMO
时间: 2023-08-12 12:33:43 浏览: 134
多路复用技术
5星 · 资源好评率100%
下面是一个使用C++编写的多路复用技术的DEMO程序,可以同时监听多个TCP客户端连接,并处理客户端发送的数据。
```c++
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <cstring>
#include <vector>
#define MAX_CLIENT_NUM 10 // 最大客户端数
#define BUFFER_SIZE 1024 // 缓冲区大小
using namespace std;
int main() {
int server_fd, max_fd, ready_num, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
char buffer[BUFFER_SIZE];
fd_set read_fds, all_fds;
vector<int> client_fds;
// 创建TCP服务器
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(1);
}
// 绑定服务器地址和端口
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8888);
if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(1);
}
// 开始监听
if (listen(server_fd, 5) == -1) {
perror("listen");
exit(1);
}
// 初始化fd_set
FD_ZERO(&all_fds);
FD_SET(server_fd, &all_fds);
max_fd = server_fd;
while (true) {
// 复制fd_set
read_fds = all_fds;
// 使用select监听
ready_num = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if (ready_num == -1) {
perror("select");
exit(1);
}
// 检查是否有新的客户端连接
if (FD_ISSET(server_fd, &read_fds)) {
client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
if (client_fd == -1) {
perror("accept");
continue;
}
// 将新的客户端连接加入fd_set
if (client_fds.size() < MAX_CLIENT_NUM) {
client_fds.push_back(client_fd);
FD_SET(client_fd, &all_fds);
if (client_fd > max_fd) {
max_fd = client_fd;
}
cout << "New client connected: " << inet_ntoa(client_addr.sin_addr) << endl;
} else {
cout << "Too many clients, reject client: " << inet_ntoa(client_addr.sin_addr) << endl;
close(client_fd);
}
// 如果没有其他的可读描述符,则跳过后面的操作
if (--ready_num == 0) {
continue;
}
}
// 处理所有可读的客户端连接
for (auto iter = client_fds.begin(); iter != client_fds.end(); iter++) {
if (FD_ISSET(*iter, &read_fds)) {
int len = recv(*iter, buffer, BUFFER_SIZE, 0);
if (len <= 0) {
// 客户端关闭连接,从fd_set中移除
cout << "Client disconnected: " << inet_ntoa(client_addr.sin_addr) << endl;
close(*iter);
FD_CLR(*iter, &all_fds);
iter = client_fds.erase(iter);
} else {
// 处理客户端发送的数据
buffer[len] = '\0';
cout << "Received from client: " << buffer << endl;
}
// 如果没有其他的可读描述符,则跳过后面的操作
if (--ready_num == 0) {
break;
}
}
}
}
return 0;
}
```
在该程序中,使用select函数监听所有可读的描述符,包括服务器和客户端连接。如果有新的客户端连接,就将其加入到客户端连接列表中,并将其加入到fd_set中。如果有客户端发送数据,就从客户端连接列表中查找该客户端,并处理其发送的数据。如果客户端关闭连接,就将其从客户端连接列表和fd_set中移除。需要注意的是,该程序是一个简单的DEMO,没有进行错误处理和容错处理,实际使用时需要进行相应的处理。
阅读全文