IO复用——select(Linux下C语言实现)

    科技2025-11-13  7

    服务器

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> #include<sys/select.h> #define MAX_FD 128 #define DATALEN 1024 //初始化服务器端套接字 int InitSocket() { int sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1)return -1; struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family=AF_INET; saddr.sin_port=htons(6000); saddr.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)); if(res==-1) { printf("bind errno\n"); return -1; } res=listen(sockfd,5); if(res==-1) { printf("listen errno\n"); return -1; } return sockfd; } //初始化记录服务器套接字到数组 void InitFds(int fds[],int n) { int i=0; for(;i<n;i++) { fds[i]=-1; } } //将套接字描述符添加到数组中 void AddFdToFds(int fds[],int fd,int n) { int i=0; for(;i<n;i++) { if(fds[i]==-1) { fds[i]=fd; break; } } } //删除数组中到套接字描述符 void DelFdFromFds(int fds[],int fd,int n) { int i=0; for(;i<n;i++) { if(fds[i]==fd) { fds[i]=-1; break; } } } //将数组的套接字描述符设置到fd_set变量中,并返回当前最大的文件描述符值 int SetFdToFdset(fd_set *fdset,int fds[],int n) { FD_ZERO(fdset);//清除fdset的所有位 int i=0,maxfd=fds[0]; for(;i<n;i++) { if(fds[i]!=-1) { FD_SET(fds[i],fdset);//设置fdset的位fd if(fds[i]>maxfd) { maxfd=fds[i]; } } } return maxfd; } //获取客户端连接 void GetClientLink(int sockfd,int fds[],int n) { struct sockaddr_in caddr; memset(&caddr,0,sizeof(caddr)); socklen_t len=sizeof(caddr); int c =accept(sockfd,(struct sockaddr*)&caddr,&len); if(c<0) { return; } printf("A client is connected\n"); AddFdToFds(fds,c,n); } //处理客户端数据 void DealClientData(int fds[],int n,int clifd) { char data[DATALEN]={0}; int num=recv(clifd,data,DATALEN-1,0); if(num<=0) { DelFdFromFds(fds,clifd,n); close(clifd); printf("A client is disconnected\n"); } else { printf("%d:%s\n",clifd,data); send(clifd,"OK",2,0); } } //处理select返回到就绪事件 void DealReadyEvent(int fds[],int n,fd_set *fdset,int sockfd) { int i=0; for(;i<n;i++) { if(fds[i]!=-1 && FD_ISSET(fds[i],fdset)) { if(fds[i]==sockfd) { GetClientLink(sockfd,fds,n); } else { DealClientData(fds,n,fds[i]); } } } } int main() { int sockfd=InitSocket(); assert(sockfd!=-1); fd_set readfds; int fds[MAX_FD]; InitFds(fds,MAX_FD); AddFdToFds(fds,sockfd,MAX_FD); while(1) { int maxfd=SetFdToFdset(&readfds,fds,MAX_FD); struct timeval timeout; timeout.tv_sec=2;//秒数 timeout.tv_usec=0;//微秒数 int n=select(maxfd+1,&readfds,NULL,NULL,&timeout); if(n<0) { printf("select error\n"); break; } else if(n==0) { printf("time out\n"); continue; } DealReadyEvent(fds,MAX_FD,&readfds,sockfd); } exit(0); }
    Processed: 0.010, SQL: 8