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
|
<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 002</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER>
<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER>
<P>
<HR WIDTH="100%">
<P>Like Tutorial 1, this is also a rather small program. I'm going
to add a couple of new ideas along the way but to make up for it I'm also
going to simplify the acceptor a great deal.
<P>We begin by looking at the <A HREF="server.cpp">main</A> portion program:
<P>
<HR WIDTH="100%">
<PRE>
/*
As before, we need a few ACE objects as well as our Logging_Handler declaration.
*/
#include "ace/Acceptor.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Reactor.h"
#include "handler.h"
/*
We'll still use the global reactor pointer. There's a snappy way around this
that shows up in later server tutorials.
*/
ACE_Reactor * g_reactor;
/*
This was hinted at in Tutorial 1. Remember the hand-coded acceptor that we
created there? This template does all of that and more and better. If you
find yourself creating code that doesn't feel like a part of your application,
there's a good chance that ACE has a template or framework component to do
it for you.
*/
typedef ACE_Acceptor < Logging_Handler, ACE_SOCK_ACCEPTOR > Logging_Acceptor;
/*
One of the new things will be a signal handler so that we can exit the application
somewhat cleanly. The 'finished' flag is used instead of the previous infninite
loop and the 'handler' will set that flag in respose to SIGINT (CTRL-C).
*/
static sig_atomic_t finished = 0;
extern "C" void handler (int)
{
finished = 1;
}
static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
int main (int, char **)
{
// Create the reactor we'll register our event handler derivatives with.
g_reactor = new ACE_Reactor;
// Create the acceptor that will listen for client connetions
Logging_Acceptor peer_acceptor;
/*
Notice how similar this is to the open() call in Tutorial 1. I read
ahead when I created that one so that it would come out this way...
*/
if (peer_acceptor.open (ACE_INET_Addr (PORT), g_reactor) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
/*
Here's the easiest way to respond to signals in your application. Simply
construct an ACE_Sig_Action object with a "C" function and the signal you
want to capture. As you might expect, there is also a way to register
signal handlers with a reactor but we take the easy-out here.
*/
ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n"));
// Perform logging service until the signal handler receives SIGINT.
while (!finished)
g_reactor->handle_events ();
// Close the acceptor so that no more clients will be taken in.
peer_acceptor.close();
// Free up the memory allocated for the reactor.
delete g_reactor;
ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server logging daemon\n"));
return 0;
}</PRE>
<P>
<HR WIDTH="100%">
<CENTER></CENTER>
<CENTER>[<A HREF="..">Tutorial
Index</A>] [<A HREF="page01.html">Previous
Page</A>] [<A HREF="page03.html">Continue
This Tutorial</A>]</CENTER>
</BODY>
</HTML>
|