select 服务器,使用bitmap存储文件描述符进行监听IO,当监听的对象发生变化,进行置为1。使用vector和bitmap进行维护监听的IO,响应的IO分为socket listen 和 message ,前者进行accept创建通话的socket,后者进行通话(接收-recv).代码如下:
server.h
#pragma once
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
using namespace std;
namespace ser{
class server{
public:
static int Socket(){
int sd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sd<0)
exit(1);
else
return sd;
}
static bool Bind(int sd,uint32_t port){
struct sockaddr_in laddr;
laddr.sin_family=AF_INET;
laddr.sin_port=htons(port);
laddr.sin_addr.s_addr=INADDR_ANY;
if(bind(sd,(const sockaddr*)&laddr,(socklen_t)sizeof laddr)<0)
exit(1);
return true;
}
static bool Listen(int sd){
if(listen(sd,6)<0)
exit(1);
return true;
}
};
}
select_.h
#pragma once
#include<vector>
#include<unistd.h>
#include<time.h>
#include"server.h"
#include<algorithm>
namespace select_server{
class select_server{
private:
int listen_sd;//the sock_fd to connect and message
int port;
public:
select_server(int _port):port(_port){}
//init server
void InitServer(){
listen_sd=ser::server::Socket();
ser::server::Bind(listen_sd,port);
ser::server::Listen(listen_sd);
}
void Run(){
std::vector<int> readfds_arry(1024,-1);
readfds_arry[0]=listen_sd;
fd_set fds_read;
while(1){
FD_ZERO(&fds_read);
//put the fd int array to bitmap fds_read
for(int i=0;i<1024;++i){
if(readfds_arry[i]!=-1)
FD_SET(readfds_arry[i],&fds_read);
}
int max_fd=*max_element(readfds_arry.begin(),readfds_arry.end());
switch(select(max_fd+1,&fds_read,NULL,NULL,NULL)){ // if the fd
//changed return > 0
case 0:
cout<<"select timeout"<<endl;
break;
case -1:
cout<<"select error"<<endl;
break;
default:
//have read thing
{
Solution(readfds_arry,fds_read);//array bitmap
}
break;
}
}
}
void Solution(vector<int>&v,fd_set& fds){
for(int i=0;i<v.size();i++){
if(FD_ISSET(v[i],&fds)){
if(v[i]==listen_sd){ //new link is not old link
//new link is coming
struct sockaddr raddr;//remoate address
socklen_t len;
int new_sd=accept(listen_sd,&raddr,&len);
cout<<"This is Connect and Message sock_fd"<<new_sd<<endl;
//put the new_link into array
if(AddfdsArray(v,new_sd)){
cout<<"Add new_sd is successed!"<<endl;
}
else
cout<<"Add new_sd is failed!"<<endl;
}
else
{
//Other thing is ready
char str[1024];
int sz=recv(v[i],&str,sizeof str,MSG_DONTWAIT);
switch(sz){
case 0:
v[i]=-1;
cout<<"The raddr is closed......"<<endl;
break;
case -1:
cout<<"Read failed.";
break;
default:
str[sz]='\0';
cout<<"Sussed :"<<str<<endl;
send(v[i],"Hello",6,0);
break;
}
}
}
}
}
bool AddfdsArray(vector<int>& v,int sd){
for(int i=0;i<v.size();i++){
if(v[i]==-1){
v[i]=sd;
return true;
}
}
return false;
}
};
}
select._cpp
#include"select_server.h"
int main(int argc,char** argv){
if(argc!=2){
cout<<"Error:argument is little"<<endl;
exit(1);
}
select_server::select_server* sl =new select_server::select_server(stoi(argv[1]));
sl->InitServer();
sl->Run();
return 0;
}