我用set存储文件描述符,复杂度会更高。
如果用vector管理所有文件描述符的话,一个描述符连接关闭删除复杂度较高。用set在Log复杂度删除,感觉更方便一点。
复杂度更低的一个思路:
开辅助数组/Vector存,再开一个数组存标志位(是否连接)。
//复用服务器
#include <unp.h>
#include <iostream>
#include <set>
#include <functional>
#include <math.h>
using namespace std;
using namespace placeholders;
typedef void (*func)(int,int);
int main(){
int m_socket=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(60000);
// cout<<addr.sin_port<<endl;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
int tlen=1;
if(setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,&tlen,sizeof(tlen))<0){
perror("setsocket error"); exit(-1);
}
if(bind(m_socket,(SA*)&addr,sizeof(addr))<0){
perror("bind error"); exit(-1);
}
if(listen(m_socket,10)<0){
perror("listen error"); exit(-1);
}
int maxfd=0;
fd_set allfd;
timeval timeout{3,0};
set<int> s;
s.insert(m_socket);
while(1){
int now;
FD_ZERO(&allfd);
for(auto i:s){
FD_SET(i,&allfd);
maxfd=max(maxfd,i+1);
}
switch(now=select(maxfd,&allfd,NULL,NULL,NULL)){
case -1: perror("select error"); exit(-1);
case 0: break;
default:
if(FD_ISSET(m_socket,&allfd)){
int d_socket=accept(m_socket,NULL,NULL);
if(d_socket<0){
perror("accept error"); exit(-1);
}
cout<<d_socket<<" 连接成功 "<<endl;
s.insert(d_socket);
maxfd=max(maxfd,d_socket+1);
}
for(auto i:s){
if(i==m_socket) continue;
if(FD_ISSET(i,&allfd)){
cout<<i<<" 有数据到 "<<endl;
char buf[1024];
int len=recv(i,buf,sizeof(buf)-1,0);
if(len==0){
FD_CLR(i,&allfd);
cout<<i<<" 关闭连接 "<<endl;
s.erase(i);
close(i);
}
else if(len<0){
perror("recv error"); exit(-1);
}
else{
buf[len]='\0';
cout<<buf<<endl;
}
}
}
}
// cout<<now<<endl;
}
return 0;
}