下面是一个基于UDP非阻塞IO的高并发Demo的C代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_BUFFER_SIZE 1024
#define MAX_CLIENTS 1000
int main() {
int serverSocket, clientSockets[MAX_CLIENTS];
struct sockaddr_in serverAddr, clientAddr;
char buffer[MAX_BUFFER_SIZE];
socklen_t addrLen = sizeof(clientAddr);
// 创建服务器socket
if ((serverSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Failed to create socket");
exit(1);
}
// 设置服务器socket为非阻塞模式
int flags = fcntl(serverSocket, F_GETFL, 0);
fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK);
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345); // 设置端口号
serverAddr.sin_addr.s_addr = INADDR_ANY;
// 绑定服务器地址和端口号
if (bind(serverSocket, (struct sockaddr *)&serverAddr , sizeof(serverAddr)) == -1) {
perror("Failed to bind");
exit(1);
}
printf("Server started. Listening for incoming connections...\n");
fd_set readfds; // 可读文件描述符集合
int maxSockFd = serverSocket + 1; // 最大文件描述符值+1
while (1) {
FD_ZERO(&readfds); // 清空可读文件描述符集合
FD_SET(serverSocket, &readfds); // 将服务器socket加入到可读文件描述符集合
// 检测所有客户端socket,并将其加入到可读文件描述符集合中
for (int i = 0; i < MAX_CLIENTS; i++) {
if (clientSockets[i] > 0) {
FD_SET(clientSockets[i], &readfds);
if (clientSockets[i] >= maxSockFd) {
maxSockFd = clientSockets[i] + 1;
}
}
}
// 使用select函数进行IO多路复用,监听可读事件
if (select(maxSockFd, &readfds, NULL, NULL, NULL) == -1) {
perror("Failed to select");
exit(1);
}
// 如果服务器socket有可读事件,则处理新的连接请求
if (FD_ISSET(serverSocket, &readfds)) {
int newClientSocket;
// 接受新的客户端连接
if ((newClientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &addrLen)) == -1) {
perror("Failed to accept");
exit(1);
}
printf("New connection established. Client socket: %d\n", newClientSocket);
// 将新的客户端socket设置为非阻塞模式,并添加到客户端socket数组中
flags = fcntl(newClientSocket, F_GETFL, 0);
fcntl(newClientSocket, F_SETFL, flags | O_NONBLOCK);
for (int i = 0; i < MAX_CLIENTS; i++) {
if (clientSockets[i] == 0) {
clientSockets[i] = newClientSocket;
break;
}
}
}
// 遍历所有客户端socket,检查是否有数据可读
for (int i = 0; i < MAX_CLIENTS; i++) {
if (clientSockets[i] > 0 && FD_ISSET(clientSockets[i], &readfds)) {
memset(buffer, '\0', sizeof(buffer));
// 接收客户端发送的数据
ssize_t bytesRead = recvfrom(clientSockets[i], buffer, sizeof(buffer), 0, (struct sockaddr *)&clientAddr, &addrLen);
if (bytesRead > 0) {
printf("Received data from client %d: %s\n", clientSockets[i], buffer);
// 这里可以添加业务逻辑处理
// 将数据回传给客户端
sendto(clientSockets[i], buffer, strlen(buffer), 0, (struct sockaddr *)&clientAddr, addrLen);
}
else if (bytesRead == 0) { // 客户端关闭连接
printf("Client %d disconnected.\n", clientSockets[i]);
close(clientSockets[i]);
clientSockets[i] = 0;
}
else if (errno != EWOULDBLOCK && errno != EAGAIN) { // 发生错误
perror("Failed to receive");
close(clientSockets[i]);
clientSockets[i] = 0;
}
}
}
}
close(serverSocket);
return 0;
}
这个示例代码使用UDP协议实现了一个基于非阻塞IO的高并发服务器。它使用select函数进行IO多路复用,可以同时处理多个客户端连接。你可以根据自己的需求进行适当的修改和扩展,添加业务逻辑处理部分。
内容由零声教学AI助手提供,问题来源于学员提问