summaryrefslogtreecommitdiff
path: root/docs/tutorials/001/page02.html
blob: f5979936078bbbf64fb954894a0563bd4841619d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]">
   <META NAME="Author" CONTENT="James CE Johnson">
   <META NAME="Description" CONTENT="A first step towards using ACE productively">
   <TITLE>ACE Tutorial 001</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

<CENTER><B><FONT SIZE=+2>ACE Tutorial 001</FONT></B></CENTER>

<CENTER><B><FONT SIZE=+2>A Beginners Guide to Using the ACE Toolkit</FONT></B></CENTER>


<P>
<HR WIDTH="100%">

<P>From here, I want to move on to the main program loop. In a way, we're
starting at the final product when we do this, but it is a very simple
piece of code and a good place to start.

<P>The <A HREF="server.cpp">main</A>
program is really quite simple. The real work is done in the ACE derived
classes.

<P>
<HR WIDTH="100%">
<PRE>/*
&nbsp; Include the header file where our client acceptor is defined.
&nbsp;*/
#include "ace/Reactor.h"

/*&nbsp;&nbsp;
&nbsp; For simplicity, we create our reactor in the global address space.
&nbsp; In later tutorials we will do something more clever and appropriate. However,
&nbsp; the purpose of this tutorial is to introduce a connection acceptance and
&nbsp; handling, not the full capabilities of a reactor.
*/
ACE_Reactor * g_reactor;

/*
&nbsp; Include the header where we define our acceptor object.&nbsp; An acceptor is
&nbsp; an abstraction that allows a server to "accept" connections from clients.
*/
#include "acceptor.h"

/*
&nbsp; A TCP/IP server can listen to only one port for connection requests.
&nbsp; Well-known services can always be found at the same address. Lesser-known
&nbsp; services are generally told where to listen by a configuration file or
&nbsp; command-line parameter. For this example, we're satisfied with simply hard-coding
&nbsp; a random but known value.
*/
static const u_short PORT = ACE_DEFAULT_SERVER_PORT;

int main (int, char **)
{
&nbsp; /*
&nbsp;&nbsp;&nbsp; Create a Reactor instance.&nbsp; Again, a global pointer isn't exactly the
&nbsp;&nbsp;&nbsp; best way to handle this but for the simple example here, it will be OK.
&nbsp;&nbsp;&nbsp; We'll get cute with it later.
&nbsp; */
&nbsp; g_reactor = new ACE_Reactor;

&nbsp; /*
&nbsp;&nbsp;&nbsp; Like the Reactor, I'm skimming over the details of the ADDR
&nbsp;&nbsp;&nbsp; object. What it provides is an abstraction for addressing services in the
&nbsp;&nbsp;&nbsp; network. All we need to know at this point is that we are creating an address
&nbsp;&nbsp;&nbsp; object which specifies the TCP/IP port on which the server
&nbsp;&nbsp;&nbsp; will listen for new connection requests.
&nbsp; */
&nbsp; ACE_INET_Addr addr (PORT);

&nbsp; /*
&nbsp;&nbsp;&nbsp; We now create an acceptor object.&nbsp; No connections will
&nbsp;&nbsp;&nbsp; yet be established because the object isn't "open for business"
&nbsp;&nbsp;&nbsp; at this time. Which brings us to the next line...
&nbsp; */
&nbsp; Logging_Acceptor * peer_acceptor = new Logging_Acceptor();

&nbsp; /*
&nbsp;&nbsp;&nbsp; where the acceptor object is opened.&nbsp; You'll find that most ACE
&nbsp;&nbsp;&nbsp; objects have to be open()ed before they're of any use to you.
&nbsp;&nbsp;&nbsp; On this open() call, we're telling the acceptor where to listen
&nbsp;&nbsp;&nbsp; for connections via the 'addr' object.&nbsp; We're also telling it
&nbsp;&nbsp;&nbsp; that we want it to be registered with our 'g_reactor' instance.
&nbsp;&nbsp; */
&nbsp; if (peer_acceptor->open(addr,g_reactor) == -1 )
&nbsp;&nbsp;&nbsp; ACE_ERROR_RETURN ((LM_ERROR, "Opening Acceptor\n"), -1);

&nbsp; ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n"));

&nbsp; /*
&nbsp;&nbsp;&nbsp; The reactor's handle_events member function is responsible for looking at
&nbsp;&nbsp;&nbsp; all registered objects and invoking an appropriate member function when
&nbsp;&nbsp;&nbsp; anything of interest occurs. When an event is processed, the handle_events
&nbsp;&nbsp;&nbsp; function returns. In order to get all events, we embed this in an infinite
&nbsp;&nbsp;&nbsp; loop.

&nbsp;&nbsp;&nbsp; Since we put ourselves into an infinite loop, you'll need to CTRL-C
&nbsp;&nbsp;&nbsp; to exit the program.
&nbsp; */
&nbsp; while (1)
&nbsp;&nbsp;&nbsp;&nbsp; g_reactor-> handle_events ();

&nbsp; return 0;
}</PRE>

<HR WIDTH="100%">

<P>As I said, the main program is really quite simple:
<UL>
<LI>
Create an address for the <I>port</I> we want to listen to</LI>

<LI>
Create an acceptor which listens on that address</LI>

<LI>
Register the acceptor with a reactor to respond to the connection requests</LI>

<LI>
Enter an infinite loop to let the reactor handle the events</LI>
</UL>
On the next page, we will take a look at the acceptor and how it responds
to new connection requests.

<P>
<HR WIDTH="100%">
<CENTER>[<A HREF="..">Tutorial
Index</A>] [<A HREF="page01.html">Previous
Page</A>] [<A HREF="page03.html">Continue
This Tutorial</A>]</CENTER>

</BODY>
</HTML>