IO多路复用
#include<myhead.h>
#define IP "192.168.114.33"
int key_events(void)
{
char buf[256];
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
printf(":%s\n",buf);
return 0;
}
int main(int argc, const char *argv[])
{
//创建一个套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
perror("socket error");
return -1;
}
printf("socket success\n");
//输入本机的IP地址和端口
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(8888);
sin.sin_addr.s_addr=inet_addr(IP);
//绑定本机的IP地址和端口
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//将套接字转换成被监听状态
if(listen(sfd,256)<0)
{
perror("listen error");
return -1;
}
printf("listen success\n");
fd_set readfds,tempfds;
//清空合集
FD_ZERO(&readfds);
//把0号和sfd文件名描述符添加到合集中
FD_SET(0,&readfds);
FD_SET(sfd,&readfds);
//创建一个新的文件描述符
int newfd=-1;
struct sockaddr_in cin;
socklen_t len=sizeof(cin);
int maxfd=sfd;
char buf[256];
int sel=-1;
ssize_t res =-1;
struct sockaddr_in savecin[1024]; //备份链接成功的客户端的地址信息,用下标来对应文件描述符
while(1)
{
tempfds=readfds;
sel=select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(sel<0)
{
perror("select error");
return -1;
}
if(0==sel)
{
printf("time out\n");
return -1;
}
for(int i=0;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds)== 0)
continue; //判断i是否在tempdfs合集中
if(0==i) //触发键盘输入事件
{
printf("键盘触发事件\n");
key_events();
}
else if(sfd==i) //客户端连接事件
{
printf("客户端连接事件\n");
//获取客户端信息
newfd=accept(i,(struct sockaddr *)&cin,&len);
if(newfd<0)
{
perror("accept error");
return -1;
}
printf("[%s:%d]客户端链接成功,newfd=%d\n",inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),newfd);
//将cin存储到对应的newfd下标的位置
savecin[newfd]=cin;
//向readfds合集中加入newfd
FD_SET(newfd,&readfds);
maxfd=maxfd>newfd?maxfd:newfd;
}
else //客户端交互事件
{
printf("客户端交互事件\n");
bzero(buf,sizeof(buf));
res=recv(i,buf,sizeof(buf),0);
if(res<0)
{
perror("recv error");
return -1;
}else if(0==res)
{
close(i);
FD_CLR(i,&readfds);
while(FD_ISSET(maxfd,&readfds)==0 && maxfd-- >= 0);
printf("[%s:%d]客户端链接断开,newfd=%d\n",inet_ntoa(savecin[i].sin_addr),\
ntohs(savecin[i].sin_port),i);
}
else
{
printf("[%s:%d]newfd=%d:%s\n",inet_ntoa(savecin[i].sin_addr),\
ntohs(savecin[i].sin_port),i,buf);
if(send(i,buf,sizeof(buf),0)<0)
{
perror("send error");
return -1;
}
printf("send success\n");
}
}
}
}
return 0;
}