In this example, ACE Proactor is used to implement echo server.
The Code volume is about 1/3 of the completion port
Implementation of ACE Reactor
Http://www.cppblog.com/sandy/archive/2006/02/17/3308.html
Complete port implementation
Http://www.cppblog.com/sandy/archive/2007/06/06/25670.html
Of course, if you understand the complete port, ACE Proactor is easy.
The general process is like this.
1. Use ACE_Asynch_Acceptor to establish the socket on the server, bind and listen wait for Accept and create IOCP
(ACE_Acceptor relative to ACE Reactor)
2. When a completion event (GetQueuedCompletionStatus) is returned, the user's processing interface is called for processing. This is a subclass derived from ACE_Service_Handler.
(ACE_Svc_Handler relative to ACE Reactor)
The biggest difference between ACE Reactor and Proactor is
When processing read/write events, ACE Reactor uses peer (). recv/send to receive/send data.
While ACE Proactor processes read/write events, the data has been read to the user's buffer zone. A typical "first cut and then play"
Ace proactor is more troublesome than Ace reactor because it needs to manually deliver asynchronous read/write requests.
You can use the following code to understand.
=========== Code ==========================
# Ifdef _ DEBUG
# Pragma comment (lib, "ACED. lib ")
# Else
# Pragma comment (lib, "ACE. lib ")
# Endif
# Include "ACE/OS _main.h"
# Include "ACE/OS _ns_sys_socket.h"
# Include "ACE/ace. H"
# Include "ACE/service_object.h"
# Include "ACE/asynch_io.h"
# Include "ACE/proactor. H"
# Include "ACE/message_block.h"
# Include "ACE/asynch_acceptor.h"
# Include "ACE/inet_addr.h"
Class echo_service: Public ace_service_handler
{
Public:
~ Echo_service ()
{
If (this-> handle ()! = Ace_invalid_handle)
ACE_ OS: closesocket (this-> handle ());
}
Virtual void open (ACE_HANDLE h, ACE_Message_Block &)
{
This-> handle (h );
If (this-> reader _. open (* this )! = 0 | this-> writer _. open (* this )! = 0)
{
ACE_ERROR (LM_ERROR, ACE_TEXT ("% p/n"), ACE_TEXT ("Echo_Service open ")));
Delete this;
Return;
}
ACE_Message_Block * mb;
ACE_NEW_NORETURN (mb, ACE_Message_Block (1024 ));
If (this-> reader _. read (* mb, mb-> space ())! = 0)
{
ACE_ERROR (LM_ERROR, ACE_TEXT ("% p/n"), ACE_TEXT ("Echo_Service begin read ")));
Mb-> release ();
Delete this;
Return;
}
}
Virtual void handle_read_stream (const ACE_Asynch_Read_Stream: Result & result)
{
ACE_Message_Block & mb = result. message_block ();
If (! Result. success () | result. bytes_transferred () = 0)
{
Mb. release ();
Delete this;
}
Else
{
If (this-> writer _. Write (MB, MB. Length () =-1)
{
Ace_error (lm_error,
Ace_text ("% P/N "),
Ace_text ("Starting write ")));
MB. Release ();
}
Else
{
Ace_message_block * new_mb;
Ace_new_noreturn (new_mb, ace_message_block (1024 ));
This-> reader _. Read (* new_mb, new_mb-> space ());
}
}
Return;
}
Virtual void handle_write_stream
(Const ace_asynch_write_stream: Result & result)
{
Ace_message_block & MB = result. message_block ();
MB. Release ();
Return;
}
PRIVATE:
Ace_asynch_read_stream reader _;
Ace_asynch_write_stream writer _;
};
Typedef ace_asynch_acceptor <echo_service> myacceptor;
Int main (INT argc, char * argv [])
{
Ace_inet_addr ADDR (1500 );
Myacceptor server;
If (server. Open (ADDR) =-1)
{
Ace_debug (lm_debug,
Ace_text ("(% p | % t) % P/N "),
Ace_text ("bind failed ")));
Return 1;
}
While (1 ){
ACE_Proactor: instance ()-> proactor_run_event_loop ();
}
Return 0;
}