10_10
I/O复用方法:select poll epoll
文件描述符:select > 0
fd_set,fd_isset,检测多个描述符,程序处理多个文件描述符
Http服务器端代码:
```c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.t>
#include<arpa/inet.h>
#include<assert.h>
#include<fcntl.h>
#include<sys/select.h>
#include<syys/time.h>
#define MAX 10
int socket_init();
void fds_init(int fds[])
{
if(fds==NULL)
{
return;
}
for(int i=0;i<MAX;i++)
{
fds[i]=-1;
}
}
void fds_add(int fd,int fds())//添加描述符
{
if(fds==NULL)
{
return;
}
for(int i=0;i<MAX;i++)
{
if(fds[i]==-1)
{
fds[i]=fd;
break;
}
}
}
void fds_del(int fd,int fds[])//移除数组指定描述符
{
if(fds==NULL)
{
return ;
}
for(int i=0;i<MAX;i++)
{
if(fds[i]==fd)
{
fds[i]=-1;
break;
}
}
}
int main()
{
int socket=socket_init;
assert(sockfd!=-1);
int fds[MAX];
fds_init(fds);//初始化数组值为-1,代表数组为空
fds_add(sockfd,fds);//将监听套接字添加到数组中
fd_set fdset;//集合 ->select
while(1)
{
FD_ZERO(&fdset);//清空集合
int maxfd=-1;//记录描述符最大值,最大值传给select
for(int i=0;i<MAX;i++)//将数组有效值传入
{
if(fds[i]==-1)
{
continue;
}
FD_SET(fds[i],&fdset)//把有效描述符添加到集合,并且找到最大值添加
if(maxfd<fds[i])
{
maxfd=fds[i];
}
}
struct timeval tv={
5,0};
int n=select(maxfd+1,&fdset,NULL,NULL,&tv);//有可能会发生阻塞,如果超时的话
if(n==-1)
{
continue;
}
else if(n==0)
{
printf("time out\n");
continue;
}
else
{
for(int i=0;i<MAX;i++)//遍历所有描述符,找到就绪的,找到所有有数据的
{
if(fds[i]==-1)//清除空位
{
continue;
}
if(FD_ISSET(fds[i],&fdset))
{
if(fds[i]==sockfd)
{
struct sockaddr_in caddr;
int len=sizeof(caddr);
int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
if(c<0)
{
continue;
}
printf("accept c = %d\n",c);
fds_add(c,fds);
}
else
{
char buff[128]={
0};
int num=recv(fds[i],buff,127,0);
if(num<=0)
{
close(fds[i]);
fds_del(fds[i],fds);//从数组删除不用的描述符
printf("client close\n");
continue;
}
printf("read:%s\n",buff);
send(fds[i],"ok",2,0);
}
}
}
}
}
}
int socket_init()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
return -1;
}
struct sockaddr_in saddr;
mem(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(80);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(res==-1)
{
return -1;
}
res=listen(sockfd,5);
if(res==-1)
{
return -1;
}
return sockfd;
}
1.对方关闭描述符
2.对方发数据
3.对方链接
select都会返回