1、函数声明
poll和select类似,都是对集合里的文件描述符进行轮询
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 需要等待的事件 */
short revents; /* 实际返回的事件 */
};
- fds:存放需要检测的文件描述符(一般为结构体数组)
- nfds:要轮询的总个数
轮询是从fds[0]开始,到fds[nfds -1]结束,后面的描述符就不管了- timeout:阻塞来等待文件描述符就绪的毫秒数
<0:一直阻塞直到有文件描述符可用
0:不阻塞,立即返回
>0:阻塞指定的秒数再返回
- 返回值
成功:返回就绪的文件描述符个数(revents不为0的结构体个数)
失败:返回-1
0:超时,且没有任何文件描述符就绪
- 可以轮询的事件类型
在’events’中设置,以指示需要等待的事件
poll返回时将出现在’revents’中,以指示文件描述符的状态
/* 可以在events中设置 ,也可能在revents中返回 */
#define POLLIN 0x001 /* 数据可读 */
#define POLLPRI 0x002 /* 高优先级数据可读 */
#define POLLOUT 0x004 /* 数据可写 */
# define POLLRDNORM 0x040 /* 正常数据可读 */
# define POLLRDBAND 0x080 /* 带优先级的数据可读 */
# define POLLWRNORM 0x100 /* 正常数据可写 */
# define POLLWRBAND 0x200 /* 带优先级的数据可写 */
/* 仅仅出现再revents中 */
#define POLLERR 0x008 /* 发生错误 */
#define POLLHUP 0x010 /* 挂起 */
#define POLLNVAL 0x020 /* 无效的轮询请求(描述符被关闭) */
POLLIN | POLLPRI 相当于select中读事件
POLLOUT | POLLWRBAND 相当于select中写事件
2、实例
server.c
#include "tcp_fun.h"
#include <poll.h>
#define IP "192.168.200.134"
#define PORT 2233
#define SIZE 1026//最多可容纳1024个客户端
int main() {
int sock_fd;
int ret,nfds;
sock_fd = tcp_server_init(IP,PORT);
if(sock_fd<0){
perror("tcp_server_init");
exit(-1);
}
struct pollfd fds[SIZE];
fds[0].fd = sock_fd;
fds[0].events = POLLIN;
nfds = 1;
for(int i = 1;i<SIZE;i++){
fds[i].fd = -1;//让poll忽略
}
printf("listening....\n");
while (1){
ret = poll(fds,nfds,-1);
if(ret<0){
perror("poll");
break;
}
else if(ret == 0){
continue;
}
else{
for (int i = 0; i < nfds; i++) {
if(fds[i].revents & POLLIN){
//有新客户端连接
if(i == 0){
for(int m=0;m<SIZE;m++){
//查看是否还能接纳客户端
if(fds[m].fd == -1){
fds[m].fd = tcp_accept(fds[i].fd);
if(fds[m].fd < 0){
perror("tcp_accept");
fds[m].fd = -1;
break;
}
fds[m].events = POLLIN;
if(nfds < m+1){
//如果轮询数小于描述符的个数
nfds++;
}
break;
}
if(m==SIZE-1){
//客户端过多,先连接再关闭
int fd = tcp_accept(fds[i].fd);
close(fd);
printf("too many clients\n");
}
}
}
else{
//有客户端发消息
ret = tcp_server_chat(fds[i].fd);
if(ret <=0){
// 客户端退出或出错
close(fds[i].fd);
fds[i].fd = -1;
if(nfds == i+1){
nfds--;
}
}
}
} else if(fds[i].revents & POLLERR){
//出错处理
close(fds[i].fd);
fds[i].fd = -1;
if(nfds == i+1){
nfds--;
}
}
}
}
}
return 0;
}
client.c
#include "tcp_fun.h"
#define IP "192.168.200.134"
#define PORT 2233
int main(int argc ,char **argv) {
int fd = tcp_client_init(IP, PORT);
if(fd < 0){
perror("tcp_client_init");
}
tcp_client_chat(fd);
}