多路IO轉接 select模型
阿新 • • 發佈:2019-01-01
select函式就一socket檔案描述符監測函式,可以監測讀和寫。沒有read和write時候將阻塞在那兒,相比於多程序和多執行緒處理,它更加節省資源。廢話不多說 上demo
#include <stdio.h> #include <sys/socket.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #include <netinet/in.h> #include <pthread.h> #include <string.h> #include <stdlib.h> #define TCP_PORT 9999 #define SOCK_NUM 1024 int main() { fd_set allset,rest; int socket_ser,socket_accept; int socketfd[SOCK_NUM]; struct sockaddr_in addr,addr_c; int maxfd; char recfub[1500]; socket_ser = socket(AF_INET,SOCK_STREAM,0); bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(TCP_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(socket_ser,(struct sockaddr *)&addr,sizeof(addr)); listen(socket_ser,128); //首先監聽socket_ser FD_ZERO(&allset); FD_SET(socket_ser,&allset); memset(socketfd,-1, sizeof(socketfd)); maxfd = socket_ser; while (1) { rest = allset; //監聽maxfd+1個檔案描敘符的讀 int num = select(maxfd+1,&rest,NULL,NULL,NULL); if(num<0) { printf("伺服器掛了\n"); } //select的返回只有有讀入的檔案描述符是1 if(FD_ISSET(socket_ser,&rest)) { int i; for ( i = 0; i < SOCK_NUM; ++i) { if (socketfd[i] == -1) break; } if (SOCK_NUM == i) { printf("滿了,掛了\n"); exit(1); } //儲存新的socket bzero(&addr_c,sizeof(addr_c)); int len = sizeof(addr_c); socketfd[i] = accept(socket_ser,(struct sockaddr*)&addr_c,(socklen_t *)&len); //加入到select監控 FD_SET(socketfd[i],&allset); //更新下監測的檔案描述符序號 if(socketfd[i]>maxfd) { maxfd = socketfd[i]; } char recip[16]; printf("Ip is %s,Port is %d\n",inet_ntop(AF_INET,&addr_c.sin_addr,recip,ntohs(addr_c.sin_port))); num--; } if(num>0) { while(num) { for (int i = 0; i <SOCK_NUM ; ++i) { if(socketfd[i]>0 && FD_ISSET(socketfd[i],&rest)) { bzero(&recfub,sizeof(recfub)); int n=0; if (0 == (n=read(socketfd[i],recfub,sizeof(recfub)))) { FD_CLR(socketfd[i],&allset); printf("socket: %d關閉連線\n", socketfd[i]); close(socketfd[i]); if (socketfd[i] >= maxfd) { maxfd --; } socketfd[i]=-1; break; } else { printf("%s\n",recfub); write(socketfd[i],recfub,strlen(recfub)); } } num --; break; //處理完一個檔案描述符繼續下一個 } } } } close(socket_ser); return 0; }