一、参数介绍
#include<poll.h>
struct pollfd{
int fd; /*委托内核检测的文件描述符*/
short events; /*委托内核检测文件描述符的什么事件*/
short revents; /*文件描述符实际发生的事件*/
};
int poll(struct pollfd* fds,nfds_t nfds,int timeout);
-参数:
fds:是一个struct pollfd结构体数组,是一个需要检测的文件描述符的集合
nfds:这个是第一个参数数组中最后一个有效元素的下标+1
timeout:阻塞时长
-1:poll调用将永远阻塞,直到莫格事件发生
0:poll调用将立即返回
>0:超时值
-返回值:同select
二、代码实现
1.服务器
代码如下(示例):
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<poll.h>
int main()
{
//创建socket
int lfd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in saddr;
saddr.sin_port = htons(9999);
saddr.sin_family=AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
//绑定
bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
//监听
listen(lfd, 5);
//初始化检测的文件描述符数组
struct pollfd fds[1024];
for (int i = 0; i < 1024;i++)
{
fds[i].fd = -1;
fds[i].events = POLLIN;
}
fds[0].fd = lfd;
int nfds = 0;
while (1)
{
//调用poll系统函数,让内核帮检测那些文件描述符有数据
int ret = poll(fds, nfds + 1, -1);
if (ret == -1)
{
perror("poll");
exit(0);
}
else if (ret == 0)
{
continue;
}
else if (ret > 0)
{
//说明检测到了有文件描述符的对应的缓冲区的数据发生了改变
if (fds[0].revents & POLLIN)
{ //表示有新的客户端连接进来了
struct sockaddr_in caddr;
int len = sizeof(caddr);
int cfd = accept(lfd, (struct sockaddr *)&caddr, &len);
//将新的文件描述符加入到集合中
for (int i = 1; i < 1024;i++)
{
if(fds[i].fd==-1)
{
fds[i].fd = cfd;
fds[i].events = POLLIN;
break;
}
}
//更新最大的文件描述符的索引
nfds = nfds > cfd ? nfds : cfd;
}
for (int i = 1; i <= nfds; i++)
{
if (fds[i].revents&POLLIN)
{ //说明这个文件描述符对应的客户端发来了数据
char buf[1024] = {0};
int len = read(fds[i].fd, buf, sizeof(buf));
if (len == -1)
{
perror("read");
}
else if (len == 0)
{
printf("client closed...\n");
close(fds[i].fd);
fds[i].fd = -1;
}
else if (len > 0)
{
printf("read buf=%s\n", buf);
write(fds[i].fd, buf, strlen(buf) + 1);
}
}
}
}
}
close(lfd);
return 0;
}
2.客户端
代码如下(示例):
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
//1.创建套接字
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd==-1)
{
perror("socket");
exit(-1);
}
//2.连接服务器
struct sockaddr_in saddr;
inet_pton(AF_INET, "182.61.11.197", &saddr.sin_addr.s_addr);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(9999);
//连接服务器
int ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if(ret==-1)
{
perror("connet");
exit(-1);
}
//3.通信
char recvbuf[1024] = {0};
int i = 0;
int num = 0;
while (1)
{
char sendbuf[1024] = {0};
sprintf(sendbuf, "send data %d", num++);
write(fd, sendbuf, strlen(sendbuf) + 1);
//接收
int len = read(fd, sendbuf, sizeof(sendbuf));
if(len==-1)
{
perror("read");
return -1;
}else if(len>0)
{
printf("read buf = %s\n", sendbuf);
}else{
printf("服务器已经断开连接...\n");
break;
}
usleep(1000);
}
//关闭连接
close(fd);
return 0;
}