Ace journey -- acceptor-connector framework instance
The reactor framework of ACE is very convenient, and it is more convenient to combine acceptor-connector. The following is a daytime instance c/s application written using the acceptor-connector framework.
SVR. cpp
# Include " ACE/inet_addr.h "
# Include " ACE/sock_stream.h "
# Include " ACE/sock_acceptor.h "
# Include " ACE/log_msg.h "
# Include " ACE/acceptor. h "
# Include " ACE/svc_handler.h "
# Include < Time. h >
Class Clientservice;
Typedef ace_acceptor < Clientservice, ace_sock_acceptor > Clientacceptor;
Class Clientservice: Public Ace_svc_handler < Ace_sock_stream, ace_null_synch > {
Typedef ace_svc_handler < Ace_sock_stream, ace_null_synch > Super;
Public :
Int Open ( Void * );
Virtual Int Handle_output (ace_handle FD = Ace_invalid_handle );
};
Int Clientservice: open ( Void * P ){
If (Super: open (P) = - 1 )
Return - 1 ;
Ace_tchar peer_name [maxhostnamelen];
Ace_inet_addr peer_addr;
If ( This -> Peer (). get_remote_addr (peer_addr) = 0 && Peer_addr.addr_to_string (peer_name, maxhostnamelen) = 0 )
Ace_debug (lm_debug, ace_text ( " (% P | % t) connection from % s \ n " ), Peer_name ));
Return This -> Reactor () -> Register_handler ( This , Ace_event_handler: write_mask );
// Return 0;
}
Int Clientservice: handle_output (ace_handle FD ){
Ace_tchar peer_name [maxhostnamelen];
Ace_inet_addr peer_addr;
This -> Peer (). get_remote_addr (peer_addr );
Peer_addr.addr_to_string (peer_name, maxhostnamelen );
Ace_debug (lm_debug, ace_text ( " (% P | % T) in clientservice: handle_output connectionfrom % s \ n " ), Peer_name ));
Time_t ticks = Time (null );
Char Timebuf [ 128 ];
Memset (timebuf, 0 , Sizeof (Timebuf ));
Ace_ OS: snprintf (timebuf, Sizeof (Timebuf ), " %. 24s \ r \ n " , Ctime ( & Ticks ));
Ace_ OS: printf ( " Output = [% s] \ n " , Timebuf );
This -> Peer (). send_n (timebuf, ace_ OS: strlen (timebuf ));
This->Reactor ()->Remove_handler (This , Ace_event_handler: null_mask );
Return 0 ;
}
Int Ace_tmain ( Int , Ace_tchar * []) {
Ace_inet_addr port_to_listen ( " 50000 " );
Clientacceptor acceptor;
// Acceptor. Reactor (ace_reactor: instance ());
If (Acceptor. Open (port_to_listen) = - 1 )
Return 1 ;
Ace_reactor: instance () -> Run_reactor_event_loop ();
Return 0 ;
}
- The acceptor-connector framework is generally executed when each connected client corresponds to a clientservice object on the server. The clientservice object must be derived from ace_svc_handler, after an acceptor receives a connection request and establishes the connection, it creates an ace_acceptor template parameter clientservice Class Object and calls the open method of the object. By default, this method only adds the read event to the reactor, you need to manually call register_handler to monitor write events.
- Pay attention to the underlined line, because the daytime server does not accept any input from the client, but only sends the information to the client, so if the handle_output method is simply rewritten, by default, ace_reactor is implemented using select. The horizontally triggered SELECT statement will initiate write events multiple times in a short period of time, as long as the output buffer is not full, therefore, the underlined line is used to stop the reactor from listening to write and close the connection after sending it to the client, that is, handle_close is called. Of course, this method is effective in a single thread, and should be locked in the case of multithreading.
The following is the client part of daytime. The running process of ace_connector and ace_acceptor is similar to that of ace_acceptor.
CLI. cpp
# Include " ACE/inet_addr.h "
# Include " ACE/connector. h "
# Include " ACE/log_msg.h "
# Include " ACE/svc_handler.h "
# Include " ACE/sock_connector.h "
Class Client: Public Ace_svc_handler < Ace_sock_stream, ace_null_synch > {
Typedef ace_svc_handler < Ace_sock_stream, ace_null_synch > Super;
Public :
Int Handle_input (ace_handle );
};
Int Client: handle_input (ace_handle FD ){
Int BC;
Char Buf [ 64 ];
Ace_ OS: memset (BUF, 0 , Sizeof (BUF ));
BC = This -> Peer (). Recv (BUF, Sizeof (BUF ));
Ace_reactor: instance () -> End_reactor_event_loop ();
Write ( 1 , Buf, BC );
Return 0 ;
}
Int Ace_tmain ( Int , Ace_tchar * []) {
Ace_inet_addr SVR ( 50000 , Ace_localhost );
Ace_connector < Client, ace_sock_connector > Connector;
Client CLI;
Client * PC = & CLI;
If (Connector. Connect (PC, SVR) = - 1 )
Ace_error_return (lm_error, ace_text ( " % P \ n " ), Ace_text ( " Connect " )), 1 );
Ace_reactor: instance () -> Run_reactor_event_loop ();
Return 0 ;
}
- After receiving the data, call the reactor's end_reactor_event_loop method to end the reactor listening loop.
Compile the twoProgramMakefile
Cc = g ++
Incl = $ (ace_root)/include
Libs = $ (ace_root)/lib
Reac_cli_deps = reac_cli.cpp
Reac_svr_deps = reac_svr.cpp
. Suffixes:. cpp. o
. Cpp. O:
$ (CC)-g-I $ (incl)-C $ *. cpp
ALL: reac_cli reac_svr
Reac_cli: $ (reac_cli_deps)
$ (CC)-g-I $ (incl)-L $ (libs)-O reac_cli $ (reac_cli_deps)-Restart
Reac_svr: $ (reac_svr_deps)
$ (CC)-g-I $ (incl)-L $ (libs)-O reac_svr $ (reac_svr_deps)-then
Clean:
-RM *~
-RM reac_cli
-RM reac_svr
(Indicate the author and source when reprinting. Do not use it for commercial purposes without permission)
MoreArticleVisit my blog: http://www.cnblogs.com/logicbaby