poll
poll
#include <poll.h>
// fds 结构体类型数组 指定我们感兴趣的文件描述符上发生的可读可写和异常事件\
// nfds 遍历结合大小 左闭右开
// timeout 单位为毫秒 -1 为阻塞 0 为立即返回
int poll(struct pollfd* fds, nfds_t nfds, int timeout);
struct pollfd
{
int fd;
short events; //注册的事件, 告知poll监听fd上的哪些事件
short revents; // 实际发生的事件
}
#define exit_if(r, ...) \
{ \
if (r) \
{ \
printf(__VA_ARGS__); \
printf("errno no: %d, error msg is %s", errno, strerror(errno)); \
exit(1); \
} \
} \
struct client_info
{
char *ip_;
int port_;
};
int main(int argc, char* argv[])
{
int port = 8001;
char ip[] = "127.0.0.1";
struct sockaddr_in address;
address.sin_port = htons(port);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htons(INADDR_ANY);
int listenfd = socket(PF_INET, SOCK_STREAM, 0);
exit_if(listenfd < 0, "socket error\n");
int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
exit_if(ret == -1, "bind error\n");
ret = listen(listenfd, 5);
exit_if(ret == -1, "listen error\n");
constexpr int MAX_CLIENTS = 1024;
struct pollfd polls[MAX_CLIENTS] = {};
struct client_info clientsinfo[MAX_CLIENTS] = {};
polls[3].fd = listenfd;
polls[3].events = POLLIN | POLLRDHUP;
while (true)
{
ret = poll(polls, MAX_CLIENTS + 1, -1);
exit_if(ret == -1, "poll error\n");
for (int i = 3; i <= MAX_CLIENTS; ++i)
{
int fd = polls[i].fd;
if (polls[i].revents & POLLRDHUP)
{
polls[i].events = 0;
printf("close fd-%d from %s:%d\n", fd, clientsinfo[fd].ip_, clientsinfo[fd].port_);
}
if (polls[i].revents & POLLIN)
{
if (fd == listenfd)
{
struct sockaddr_in client_address;
socklen_t client_addresslen = sizeof(client_address);
int clientfd = accept(listenfd, (struct sockaddr*)&client_address,
&client_addresslen);
struct client_info *clientinfo = &clientsinfo[clientfd];
clientinfo->ip_ = inet_ntoa(client_address.sin_addr);
clientinfo->port_ = ntohs(client_address.sin_port);
exit_if(clientfd < 0, "accpet error, from %s:%d\n", clientinfo->ip_,
clientinfo->port_);
printf("accept from %s:%d\n", clientinfo->ip_, clientinfo->port_);
polls[clientfd].fd = clientfd;
polls[clientfd].events = POLLIN | POLLRDHUP;
}
else
{
char buffer[1024];
memset(buffer, '\0', sizeof(buffer));
ret = read(fd, buffer, 1024);
if(ret == 0)
{
close(fd);
}
else
{
printf("recv from %s:%d:\n%s\n", clientsinfo[fd].ip_,
clientsinfo[fd].port_, buffer);
}
}
}
}
}
}