IO多路复用主要包括select、poll和epoll,以下附有这三种实现方式代码参考。
提示:以下是本篇文章正文内容,下面案例可供参考
#include
#include
#include
//#include
#include
#include
#define BUF_LEN 1024
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("param port error\n");
return -1;
}
int port = atoi(argv[1]);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
perror("bind\n");
return -2;
}
if (listen(sockfd, 5) < 0)
{
perror("listen\n");
}
fd_set rfds, rset;
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
int maxfd = sockfd + 1;
while (1)
{
rset = rfds;
int nready = select(maxfd, &rset, NULL, NULL, NULL);
if (nready < 0)
{
continue;
}
if (FD_ISSET(sockfd, &rset))
{
struct sockaddr_in clientaddr;
socklen_t client_len = sizeof(clientaddr);
int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &client_len);
if (clientfd <= 0)
{
continue;
}
FD_SET(clientfd, &rfds);
if (clientfd >= maxfd)
{
maxfd = clientfd + 1;
}
printf("sockfd %d, maxfd %d, clientfd %d\n", sockfd, maxfd, clientfd);
if (--nready == 0)
{
continue;
}
}
int i = 0;
for (i = sockfd + 1; i < maxfd; i++)
{
if (FD_ISSET(i, &rset))
{
char buffer[BUF_LEN] = {0};
int ret = recv(i, buffer, BUF_LEN, 0);
if (ret < 0)
{
if ((EAGAIN == errno) || (EWOULDBLOCK == errno))
{
printf("recv all data\n");
}
else
{
FD_CLR(i, &rfds);
close(i);
if (i == maxfd - 1)
{
maxfd--;
}
continue;
}
}
else if (0 == ret)
{
printf("client close\n");
FD_CLR(i, &rfds);
close(i);
if (i == maxfd - 1)
{
maxfd--;
}
continue;
}
else
{
printf("recv %d byte data, content is [%s]\n", ret, buffer);
}
if (--nready == 0) break;
}
}
}
return 0;
}
#include
#include
#include
//#include
#include
#include
#include
#define BUF_LEN 1024
#define POLL_SIZE 1024
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("param port error\n");
return -1;
}
int port = atoi(argv[1]);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
perror("bind\n");
return -2;
}
if (listen(sockfd, 5) < 0)
{
perror("listen\n");
}
struct pollfd fds[POLL_SIZE] = {0};
fds[0].fd = sockfd;
fds[0].events = POLLIN;
int maxfd = 1, i = 0;
for (i = 1; i < POLL_SIZE; i++)
{
fds[i].fd = -1;
}
while (1)
{
int nready = poll(fds, maxfd, 5);
if (nready <= 0) continue;
if (POLLIN == (fds[0].revents & POLLIN))
{
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(struct sockaddr_in));
socklen_t client_len = sizeof(client_addr);
int clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (0 > clientfd)
{
continue;
}
char str[INET_ADDRSTRLEN] = {0};
printf("recvived from %s at port %d, sockfd:%d, clientfd:%d\n",
inet_ntop(AF_INET, &client_addr.sin_addr, str, sizeof(str)),
ntohs(client_addr.sin_port),
sockfd,
clientfd);
fds[clientfd].fd = clientfd;
fds[clientfd].events = POLLIN;
if (clientfd >= maxfd)
{
maxfd = clientfd + 1;
}
if (--nready == 0) continue;
}
for (i = 1;i < maxfd; i++)
{
if (fds[i].revents & (POLLIN|POLLERR))
{
char buffer[BUF_LEN] = {0};
int ret = recv(i, buffer, BUF_LEN, 0);
if (ret < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
printf("read all data\n");
}
else
{
close(i);
fds[i].fd = -1;
if (i == maxfd - 1)
{
maxfd--;
}
continue;
}
}
else if (ret == 0)
{
printf("disconnect %d\n", i);
close(i);
fds[i].fd = -1;
if (i == maxfd - 1)
{
maxfd--;
}
continue;
} else
{
printf("recv: %s, %d Bytes\n", buffer, ret);
}
if (--nready == 0) break;
}
}
}
return 0;
}
#include
#include
#include
//#include
#include
#include
#include
#define BUF_LEN 1024
#define EPOLL_SIZE 1024
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("param port error\n");
return -1;
}
int port = atoi(argv[1]);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
perror("bind\n");
return -2;
}
if (listen(sockfd, 5) < 0)
{
perror("listen\n");
}
int epoll_fd = epoll_create(EPOLL_SIZE); /**<参数只有0和正数之分 */
struct epoll_event ev, events[EPOLL_SIZE] = {0};
ev.events = EPOLLIN;
ev.data.fd = sockfd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &ev);
while (1)
{
int nready = epoll_wait(epoll_fd, events, EPOLL_SIZE, -1);
if (nready == -1)
{
printf("epoll_wait\n");
break;
}
int i = 0;
for (i = 0; i < nready; i++)
{
if (events[i].data.fd == sockfd)
{
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(struct sockaddr_in));
socklen_t client_len = sizeof(client_addr);
int clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (0 > clientfd)
{
continue;
}
char str[INET_ADDRSTRLEN] = {0};
printf("recvived from %s at port %d, sockfd:%d, clientfd:%d\n",
inet_ntop(AF_INET, &client_addr.sin_addr, str, sizeof(str)),
ntohs(client_addr.sin_port),
sockfd,
clientfd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = clientfd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, clientfd, &ev);
}
else
{
int clientfd = events[i].data.fd;
char buffer[BUF_LEN] = {0};
int ret = recv(clientfd, buffer, BUF_LEN, 0);
if (ret < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
printf("read all data\n");
}
else
{
close(clientfd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = clientfd;
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, clientfd, &ev);
continue;
}
}
else if (ret == 0)
{
printf("disconnect %d\n", clientfd);
close(clientfd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = clientfd;
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, clientfd, &ev);
continue;
} else
{
printf("recv: %s, %d Bytes\n", buffer, ret);
}
}
}
}
return 0;
}