ACE的Select模型

来源:互联网 发布:c语言 new 编辑:程序博客网 时间:2024/06/04 19:25


          虽然之前也在linux下写过select服务,但是用ACE还是第一次,把一些心得写下来。算是milestone吧。首先ACE相关库的下载安装我就不多废话,先说说程序的框架,该服务器分服务端和客户端。服务端的主线程负责监听新的连接,同时另起一个线程去处理数据。客户端很简单,就负责发送数据。

           服务端的主线程(负责新连接的监听):

         

#define PORT "1234"void *pthread_function(void *pArg);                 //监听客户端发送的数据int handle_data(ACE_SOCK_Stream stream);  //处理客户端stream的数据ACE_Handle_Set handle_set;std::map<std::string , ACE_SOCK_Stream> STRING_STREAM;//string - ACE_SOCK_Stream 名值对//using namespace ACE;int main(int argc , char *argv[]){ACE_SOCK_Acceptor acceptor;ACE_SOCK_Stream local_stream , remote_stream;ACE_INET_Addr local_inet_addr , remote_inet_addr;local_inet_addr.set(atoi(PORT));acceptor.open(local_inet_addr , 1);                 //1 代表设置接受者(acceptor)socket的SO_REUSEADDR,允许程序停止后重新启动,避免和前一次timeout的socket发生冲突               handle_set.set_bit(acceptor.get_handle());local_stream.set_handle(acceptor.get_handle());STRING_STREAM["127.0.0.1"]=local_stream;pthread_t tid;pthread_create(&tid , NULL , pthread_function , NULL); // new thread to handle dataint result = 0;while(1){result = acceptor.accept(remote_stream , &remote_inet_addr);          //阻塞地监听新的连接if (result < 0) {continue;}handle_set.set_bit(remote_stream.get_handle());      //将新的stream加入ACE_Handle_Set等待select监听handle_set.clr_bit(acceptor.get_handle());const char *host = remote_inet_addr.get_host_addr();STRING_STREAM[host]=remote_stream; // 将stream加入map,方便轮询}pthread_join(tid , NULL);return 0;}

         

           服务端数据接收线程 :

void *pthread_function(void *pArg){int result = 0 , width = 0;ACE_Handle_Set active_handle_set;std::map<std::string , ACE_SOCK_Stream>::iterator iter;struct timeval tv = {1, 0};ACE_Time_Value atv(tv);   //设置select的timeoutprintf("max_set = %d\n",(int)handle_set.max_set());while(1){active_handle_set = handle_set;width = (int)active_handle_set.max_set() + 1;                    /*                   *  max_set() Returns the number of the large bit.                 *                   */        if (ACE::select(width , &active_handle_set , 0 , 0 , &atv) < 1)  //ACE::select 返回活动的句柄数目{ continue;}int set_size = active_handle_set.num_set();if (set_size > 0){std::cout<<"set_size = "<<set_size<<std::endl;}for (iter = STRING_STREAM.begin() ; iter != STRING_STREAM.end() ; iter++) {                       //轮询map表,与select出的active_handle_set比较,得出需要recv的连接                if (active_handle_set.is_set((iter->second).get_handle())){ACE_INET_Addr inet_addr;(iter->second).get_remote_addr(inet_addr);std::cout<<"<==== The Data from "<<inet_addr.get_host_addr()<<" ====>"<<std::endl;handle_data(iter->second);                             //转交handle_data处理数据active_handle_set.clr_bit(iter->second.get_handle());    //数据处理完毕,清理active_handle_set}}}}

          handle_data实现:

int handle_data(ACE_SOCK_Stream stream){ACE_Message_Block *mblk = new ACE_Message_Block(8);ACE_CDR::mb_align(mblk);int rs = stream.recv_n(mblk->wr_ptr() , 8);if (rs != 8){printf("*ERROR* rs = %d\n",rs);return -1;}mblk->wr_ptr(8);ACE_InputCDR cdr(mblk);ACE_CDR::ULong length = 0;ACE_CDR::Boolean b;cdr >> ACE_InputCDR::to_boolean(b);  //获取字节序cdr.reset_byte_order(b);cdr >> length;   //获取数据长度if (length > 0) {ACE_Message_Block *data = new ACE_Message_Block(length+1);rs = stream.recv_n(data->wr_ptr() , length);   //接收数据if (rs != length){printf("*ERROR* Fail to recv data from network\n");mblk->release();mblk = 0;return -1;}data->wr_ptr(length);printf("data = %s\n",data->rd_ptr());                               /*  在这里解析数据,然后分发处理                 *                 */         data->release();       data = 0;}mblk->release();mblk = 0;return 0;}

           客户端程序:

#define HOST "192.168.1.20"int main(int argc , char *argv[]){ACE_INET_Addr inet_addr;ACE_SOCK_Stream sock_stream;ACE_Message_Block *mblk = new ACE_Message_Block(20);inet_addr.set("1234" , HOST);ACE_SOCK_Connector *connector = new ACE_SOCK_Connector();int result = connector->connect(sock_stream , inet_addr);if(result != 0){//error               return -1;        }strcpy(mblk->wr_ptr() , "Fukushimadaiichikennbazu");int length = strlen(mblk->wr_ptr());mblk->wr_ptr(length);ACE_CDR::ULong ulong(length);ACE_OutputCDR header(ACE_CDR::MAX_ALIGNMENT + 8);   //MAX_ALIGNMENT = 8header << ACE_OutputCDR::from_boolean(ACE_CDR_BYTE_ORDER);  //设置字节序header << ulong;            //设置数据长度//ACE_CDR_BYTE_ORDER = 1 means little endianiovec iov[2];iov[0].iov_base = header.begin()->rd_ptr();  //头信息iov[0].iov_len = 8;iov[1].iov_base = mblk->rd_ptr();  //数据信息iov[1].iov_len = length;sock_stream.sendv_n(iov , 2);    //立即发送sock_stream.close();mblk->release();delete connector;return 0;}


      



          

原创粉丝点击