1.select 模型
1.1 select 函数原型如下,其中 nfds 表示的描述符的最大值加1(因为这里是左闭右开区间),中间三个参数分别表示要监听的不同类型描述符的集合,timeout用来表示轮询的时间间隔,这里用NULL表示无限等待。
1.2使用 select函数编写客户端程序的一般步骤:
a)初始化参数,包括初始化监听集合read_set并添加fd,以及初始化监听的最大描述符 maxfd 和select的返回值 nready;
b)将read_set 赋值给 ready_set,因为每次执行select函数监听结合都会改变,read_set用来保存原始的集合;
c)执行 select调用,检查返回值;
d)依次检查fd,分别执行不同的操作;
1.3 程序示例。
#include "def.h"
#include
/*
* 使用select模型 编写客户端程序
*
*/
void do_service(int peerfd);
int main(int argc, const char *argv[])
{
//1.创建 socket
int peerfd = socket(AF_INET, SOCK_STREAM, 0);
if(peerfd == -1)
ERR_EXIT("socket");
//2. conncet
struct sockaddr_in peeraddr;
peeraddr.sin_family = AF_INET;
peeraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
peeraddr.sin_port = htons(9999);
if(connect(peerfd, (struct sockaddr*)&peeraddr, sizeof(peeraddr)) == -1)
ERR_EXIT("connect");
do_service(peerfd);
close(peerfd);
return 0;
}
void do_service(int peerfd){
char sendbuf[1024] = {0};
char recvbuf[1024] = {0};
//1.初始化数组,添加要监听的描述符
fd_set read_set, ready_set;
FD_ZERO(&read_set);
FD_SET(STDIN_FILENO, &read_set);
FD_SET(peerfd, &read_set);
int maxfd = STDIN_FILENO > peerfd ? STDIN_FILENO : peerfd;
int nready; //接收select的返回值
// 2.执行监听
while(1){
ready_set = read_set;
nready = select(maxfd + 1, &ready_set, NULL, NULL, NULL);
if(nready == -1){
if(errno == EINTR)
continue;
ERR_EXIT("select");
}
else if(nready == 0)
continue;
// 3.依次检查每个fd是否在集合中
if(FD_ISSET(STDIN_FILENO, &ready_set)){
if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL){
shutdown(peerfd, SHUT_WR);
//从监听集合中移除该fd
FD_CLR(STDIN_FILENO, &read_set);
}
writen(peerfd, sendbuf, strlen(sendbuf));
}
if(FD_ISSET(peerfd, &ready_set)){
int ret = readline(peerfd, recvbuf, sizeof(recvbuf));
if(ret == -1)
ERR_EXIT("readline");
else if(ret == 0){
close(peerfd);
printf("server closed\n");
break;
}
printf("recv data: %s", recvbuf);
}
}
}
2.poll模型
2.1 poll 函数
2.1.1 poll函数原型如下,第一个参数为要监听的描述符数组,第二个是数组的长度,第三个表示轮询的间隔(负值表示无限等待)。
2.1.2 poll的第一个参数结构体如下,fd即为要监听的描述符,events表示等待的事件,我们一般使用POLLIN,revents是一个传出参数,我们用它来判断等待的事件是否发生。
2.2 使用 poll 编写客户端程序的一般步骤:
a)准备数组(即poll函数的第一个参数),填入相应的 fd 和 events,定义maxi(数组下标的最大值)和nready(接收poll的返回值)变量;
b)进入w