select服务器编写

xiaoxiao2021-02-27  238

select与多进程/多线程服务器进行对比

优点

1)不需要建立多个线程、进程就可以实现一对多的通信。 2)可以同时等待多个文件描述符,效率比起多进程多线程来说要高很多。 3)select()的可移植性更好,在某些Unix系统上不支持poll() 4)select() 对于超时值提供了更好的精度:微秒,而poll是毫秒

缺点

1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大 ,循环次数有点多; 2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大 。 3)select支持的文件描述符数量太小了,默认是1024;

select 整体实现:

/************************************************************************* > File Name: select.c > Author:Steve > Mail:caoliang2025@foxmail.com > Created Time: Tue 01 Aug 2017 09:50:09 AM PDT ************************************************************************/ #include<stdio.h> #include<sys/types.h> #include<sys/select.h> #include<sys/time.h> #include<unistd.h> #include<sys/socket.h> #include<stdlib.h> #include<string.h> #include<netinet/in.h> #include<arpa/inet.h> #define SIZE sizeof(fd_set)*8 //select void Usage(char* proc) { printf("Usage:%s[local ip][local port]\n",proc); } int startUp(char* ip,int port) { //create bind listen // int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("sock"); exit(1); } int opt=1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); struct sockaddr_in local; local.sin_family=AF_INET; local.sin_addr.s_addr=inet_addr(ip); local.sin_port=htons(port); if(bind(sock,(struct sockaddr *)&local,sizeof(local))<0) { perror("bind"); exit(2); } if(listen(sock,10)<0) { perror("listen"); exit(3); } return sock; } int fds[SIZE]; int main(int argc,char*argv[]) { if(argc!=3) { Usage(argv[0]); return 1; } int listen_socket=startUp(argv[1],atoi(argv[2])); printf("listen_fd is %d\n",listen_socket); //fd_set rfds; //FD_SET(listen_socket,&rfds); int nums=SIZE; memset(fds,-1,nums); fds[0]=listen_socket; while(1) { //we need everytime to renew the rfds by fds int i=0; int max=-1; struct timeval timeout={1,0};///1s fd_set rfds; FD_ZERO(&rfds); for(;i<nums;i++) { if(fds[i]!=-1) { if(max<fds[i]) { max=fds[i]; } FD_SET(fds[i],&rfds); } } switch(select(max+1,&rfds,NULL,NULL,NULL)) { case 0 : printf("timeout..\n"); break; case -1: perror("select"); break; default: //at least a fd is ready for(i=0;i<nums;i++) { if(i==0&&FD_ISSET(listen_socket,&rfds)) { struct sockaddr_in new_client; socklen_t len=sizeof(new_client); // we can accept new client int client_sock=accept(listen_socket,\ (struct sockaddr*)&new_client,&len); if(client_sock<0) { perror("accept:"); continue; } printf("get a new client [%s][%d]\n",inet_ntoa(new_client.sin_addr),ntohs(new_client.sin_port)); int i; for(i=1;i<nums;i++) { if(fds[i]==-1) { break; } } if(i==nums) { printf("fd is full\n"); close(client_sock); } else { fds[i]=client_sock; } continue; } else if(i!=0&&FD_ISSET(fds[i],&rfds)) { //read& write char buf[1024]; ssize_t s=read(fds[i],buf,sizeof(buf)-1); if(s>0) { buf[s]=0; printf("client #%s\n",buf); write(fds[i],buf,strlen(buf)); }else if(s==0) { printf("client is quit!\n"); //connection failed close(fds[i]); fds[i]=-1; } else{ perror("read"); close(fds[i]); fds[i]=-1; } }else{ continue; } } break; } } close(listen_socket); return 0; } /************************************************************************* > File Name: client.c > Author:Steve > Mail:caoliang2025@foxmail.com > Created Time: Tue 01 Aug 2017 07:54:55 PM PDT ************************************************************************/ #include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<string.h> #include<arpa/inet.h> #include<netinet/in.h> #include<stdlib.h> void Usage(char* proc) { printf("Usage:%s[local ip][local port]\n",proc); } //client int main(int argc,char*argv[]) { if(argc!=3) { Usage(argv[0]); return 1; } int sock=socket(AF_INET,SOCK_STREAM,0); if(sock<0) { perror("socket"); return 2; } struct sockaddr_in server; server.sin_family=AF_INET; server.sin_addr.s_addr=inet_addr(argv[1]); server.sin_port=htons(atoi(argv[2])); socklen_t len=sizeof(server); if(connect(sock,(struct sockaddr*)&server,len)<0) { perror("connect"); return 3; } printf("connect is successfully\n"); char buf[1024]; while(1) { memset(buf,0,sizeof(buf)); printf("Please input:"); fflush(stdout); ssize_t s=read(0,buf,sizeof(buf)-1); if(s>0) { buf[s-1]=0; write(sock,buf,strlen(buf)); } ssize_t _s=read(sock,buf,sizeof(buf)-1); if(_s>0) { buf[_s]=0; printf("server echo:%s\n",buf); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-10453.html

最新回复(0)