1.首先,大概说一下poll函数的工作大概:(包含在#include<poll.h>当中)
poll 是通过监听一个结构体变量来对 文件描述符进行监听的(当然,socket也算是一个文件描述符)
这个结构体的大概结构是:
(!!如果不想了解poll工作原理的。可以直接拉下去看代码)
struct pollfd //这个结构体一般会被定义为结构体数组
{
int fd; //要监听的文件描述符
short events; //期待fd发生的事件 ,其中 events把他设置成 POLLIN就够用了,表示检测该fd有没有可读数据
short revents; //fd实际发生的事件
};
而poll()是通过监听上述结构体数组 来监听一堆文件描述符的
2.再来了解poll()函数详细信息:
(一)首先是他的输入参数:
int poll(struct pollfd *name,int num,int timeout);
一共有三个,分别是监听的结构体数组的数组名,实际监听着多少个结构体数组成员,阻塞时间控制参数。
其中timeout参数 ==0,是非阻塞,== -1 是阻塞,>0是阻塞 xx毫秒
(一)首先是他的输入参数:
int poll(struct pollfd *name,int num,int timeout);
一共有三个,分别是监听的结构体数组的数组名,实际监听着多少个结构体数组成员,阻塞时间控制参数。
其中timeout参数 ==0,是非阻塞,== -1 是阻塞,>0是阻塞 xx毫秒
(二)然后是他的返回值
poll()函数的返回值 ,表示同时有响应的文件描述符个数。
poll()函数的返回值 ,表示同时有响应的文件描述符个数。
接下来看看 poll()的大致使用例子:
3.给出代码:(在这之前先看看代码的大致实现逻辑)
首先把 监听套接字sock 和 标准输入 先放到 监听的结构体数组中
while(1)循环是必须的,在循环中,用poll()进行监听,然后判断是sock是否响应,是的话,就调用accept来获取连接进来的客户端的信息,并把接收到的socket放到结构体数组中。否则就继续往下(判断是否标准输入响应,是就读信息),再往下,判断是哪些客户端socket发生可读响应,有的话,就读。
//服务端
#include"myhead.h"
#define CLI_NUM 10
char rbuf[50];
char wbuf[50];
char ipbuf[50];
int recv_num;
struct pollfd pollfd[CLI_NUM];
void write_all(char *wbuf,int max)
{
int i = 2;
for(i;i<(max+2);i++)
{
write(pollfd[i].fd,wbuf,50);
}
}
int main()
{
int sockfd;
int size,port;
int new_sock;
int on = 1;
int i;
int max = 0;
int ret;
struct sockaddr_in saddr;
struct sockaddr_in caddr;
size = sizeof(struct sockaddr_in);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockfd = socket(AF_INET,SOCK_STREAM,0);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
bind(sockfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr));
listen(sockfd,10);
//init pollfd
for(i=0;i<10;i++) //把pollfd置 -1,当然不一定是-1,只是文件描述符不可能为负,所以就置成一个负数
{
pollfd[i].fd = -1;
}
pollfd[0].fd = sockfd;
pollfd[0].events = POLLIN;
pollfd[1].fd = STDIN_FILENO;
pollfd[1].events = POLLIN;
int len = sizeof(struct sockaddr);
while(1)
{
puts("waiting poll");
ret = poll(pollfd,max+2,-1); //ret表示发生响应的文件描述符个数,接下来就要对这些响应的文件描述符都处理一次
if(ret ==0)
{
perror("timeout");
exit(-1);
}
if((pollfd[0].revents& POLLIN) == POLLIN)
{
puts("waiting accept");
new_sock = accept(sockfd,(struct sockaddr*)&caddr,&len);
write(new_sock,"get",4);
if(new_sock>0)
{
//fcntl(new_sock,F_SETFL,fcntl(new_sock,F_GETFL)|O_NONBLOCK);
printf("newfd =%d\n",new_sock);
i = 2;
for(i;i<CLI_NUM;i++)
{
if(pollfd[i].fd != -1)
continue;
else if(pollfd[i].fd == -1)
{
pollfd[i].fd = new_sock;
pollfd[i].events = POLLIN;
max +=1;
printf("max=%d\n",max);
ret-=1; //每处理一个就 -1
if(ret <= 0 ) //要是响应的文件描述符都处理完了,就退出循环。
{
break;
}
}
}
}
}
if((pollfd[1].revents & POLLIN) == POLLIN) //是否从键盘有信息读入
{
bzero(wbuf,50);
scanf("%s",wbuf);
write_all(wbuf,max);
ret-=1; //每处理一个就 -1
if(ret<=0)
continue;
}
for(i=2;i<CLI_NUM && pollfd[i].fd!=-1;i++) //接收来自其他客户端的信息
{
if((pollfd[i].revents & POLLIN)==POLLIN)
{
puts("enter read");
bzero(rbuf,50);
recv_num = recv(pollfd[i].fd,rbuf,50,0);
if(recv_num == 0) //当recv_num 为0,表示客户端已经退出了
{
printf("client close\n");
close(pollfd[i].fd);
pollfd[i].fd = -1; //既然客户端退出了,那原本该客户端占着的位置就重新置 -1
continue;
}
printf("%s,from:%d\n",rbuf,pollfd[i].fd);
write_all(rbuf,max);
ret -=1;
if(ret<=0)
break;
}
}
}
}
接下来是客户端:
//客户端相对而言就比较简单
#include"myhead.h"
char rbuf[50];
char wbuf[50];
char ipbuf[50];
int main()
{
int sockfd;
int ret,port;
struct pollfd pollfd[2];
struct sockaddr_in saddr;
int size = sizeof(struct sockaddr_in);
bzero(&saddr,size);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = inet_addr("192.168.152.128");
sockfd = socket(AF_INET,SOCK_STREAM,0);
ret=connect(sockfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr));
if(ret == 0)
{
inet_ntop(AF_INET,(void*)&saddr.sin_addr.s_addr,ipbuf,50);
port = ntohs(saddr.sin_port);
printf("%s,%d\n",ipbuf,port);
}
pollfd[0].fd = STDIN_FILENO;
pollfd[0].events = POLLIN;
pollfd[1].fd = sockfd;
pollfd[1].events = POLLIN;
while(1)
{
poll(pollfd,2,-1);
if((pollfd[0].revents & POLLIN)==POLLIN)
{
puts("message from keyboard");
bzero(wbuf,50);
scanf("%s",wbuf);
write(sockfd,wbuf,50);
}
if((pollfd[1].revents & POLLIN)==POLLIN)
{
bzero(rbuf,50);
read(sockfd,rbuf,50);
printf("%s\n",rbuf);
}
}
return 0;
}