1 // This example tests the features of the <ACE_SOCK_Acceptor>,
2 // <ACE_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
3 // supports threads it uses a thread-per-connection concurrency model.
4 // Otherwise, it uses a single-threaded iterative server model.
6 #include "ace/SOCK_Acceptor.h"
7 #include "ace/Thread_Manager.h"
8 #include "ace/Handle_Set.h"
9 #include "ace/Profile_Timer.h"
10 #include "ace/Basic_Types.h"
11 #include "ace/OS_NS_sys_select.h"
12 #include "ace/OS_main.h"
13 #include "ace/Truncate.h"
16 // Are we running verbosely?
17 static int verbose
= 0;
20 run_server (ACE_THR_FUNC server
,
23 #if defined (ACE_HAS_THREADS)
24 // Spawn a new thread and run the new connection in that thread of
25 // control using the <server> function as the entry point.
26 if (ACE_Thread_Manager::instance ()->spawn (server
,
27 reinterpret_cast<void *> (handle
),
33 (*server
) (reinterpret_cast<void *> (handle
));
34 #endif /* ACE_HAS_THREADS */
37 // Function entry point into the twoway server task.
39 static ACE_THR_FUNC_RETURN
40 twoway_server (void *arg
)
42 ACE_INET_Addr cli_addr
;
43 ACE_SOCK_Stream new_stream
;
44 ACE_HANDLE handle
= (ACE_HANDLE
) (intptr_t) arg
;
46 new_stream
.set_handle (handle
);
48 // Make sure we're not in non-blocking mode.
49 if (new_stream
.disable (ACE_NONBLOCK
) == -1)
50 ACE_ERROR_RETURN ((LM_ERROR
,
54 else if (new_stream
.get_remote_addr (cli_addr
) == -1)
55 ACE_ERROR_RETURN ((LM_ERROR
,
61 "(%P|%t) client %s connected from %d\n",
62 cli_addr
.get_host_name (),
63 cli_addr
.get_port_number ()));
65 size_t total_bytes
= 0;
66 size_t message_count
= 0;
70 // Read data from client (terminate on error).
76 ssize_t r_bytes
= new_stream
.recv_n ((void *) &len
,
85 else if (r_bytes
== 0)
88 "(%P|%t) reached end of input, connection closed by client\n"));
91 else if (r_bytes
!= (ssize_t
) sizeof (ACE_INT32
))
100 len
= ACE_NTOHL (len
);
101 ACE_NEW_RETURN (request
,
106 // Subtract off the sizeof the length prefix.
107 r_bytes
= new_stream
.recv_n (request
,
108 len
- sizeof (ACE_UINT32
));
111 ACE_ERROR ((LM_ERROR
,
116 else if (r_bytes
== 0)
118 ACE_DEBUG ((LM_DEBUG
,
119 "(%P|%t) reached end of input, connection closed by client\n"));
123 && ACE::write_n (ACE_STDOUT
,
126 ACE_ERROR ((LM_ERROR
,
129 else if (new_stream
.send_n (request
,
131 ACE_ERROR ((LM_ERROR
,
135 total_bytes
+= size_t (r_bytes
);
142 // Close new endpoint (listening endpoint stays open).
149 // Function entry point into the oneway server task.
151 static ACE_THR_FUNC_RETURN
152 oneway_server (void *arg
)
154 ACE_INET_Addr cli_addr
;
155 ACE_SOCK_Stream new_stream
;
156 ACE_HANDLE handle
= (ACE_HANDLE
) (intptr_t) arg
;
158 new_stream
.set_handle (handle
);
160 // Make sure we're not in non-blocking mode.
161 if (new_stream
.disable (ACE_NONBLOCK
) == -1)
162 ACE_ERROR_RETURN ((LM_ERROR
,
166 else if (new_stream
.get_remote_addr (cli_addr
) == -1)
167 ACE_ERROR_RETURN ((LM_ERROR
,
172 ACE_DEBUG ((LM_DEBUG
,
173 "(%P|%t) client %s connected from %d\n",
174 cli_addr
.get_host_name (),
175 cli_addr
.get_port_number ()));
178 ACE_Profile_Timer timer
;
181 size_t total_bytes
= 0;
182 size_t message_count
= 0;
186 // Read data from client (terminate on error).
192 ssize_t r_bytes
= new_stream
.recv_n ((void *) &len
,
196 ACE_ERROR ((LM_ERROR
,
201 else if (r_bytes
== 0)
203 ACE_DEBUG ((LM_DEBUG
,
204 "(%P|%t) reached end of input, connection closed by client\n"));
207 else if (r_bytes
!= (ssize_t
) sizeof (ACE_INT32
))
209 ACE_ERROR ((LM_ERROR
,
216 len
= ACE_NTOHL (len
);
217 ACE_NEW_RETURN (request
,
222 // Subtract off the sizeof the length prefix.
223 r_bytes
= new_stream
.recv_n (request
,
224 len
- sizeof (ACE_UINT32
));
228 ACE_ERROR ((LM_ERROR
,
233 else if (r_bytes
== 0)
235 ACE_DEBUG ((LM_DEBUG
,
236 "(%P|%t) reached end of input, connection closed by client\n"));
240 && ACE::write_n (ACE_STDOUT
, request
, r_bytes
) != r_bytes
)
241 ACE_ERROR ((LM_ERROR
,
245 total_bytes
+= size_t (r_bytes
);
254 ACE_Profile_Timer::ACE_Elapsed_Time et
;
255 timer
.elapsed_time (et
);
257 ACE_DEBUG ((LM_DEBUG
,
258 ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
263 double messages_per_sec
= double (message_count
) / et
.real_time
;
265 ACE_DEBUG ((LM_DEBUG
,
266 ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n\t\tmessages-per-second = %0.00f\n"),
269 (((double) total_bytes
* 8) / et
.real_time
) / (double) (1024 * 1024),
270 (et
.real_time
/ (double) message_count
) * 1000000,
271 messages_per_sec
< 0 ? 0 : messages_per_sec
));
273 // Close new endpoint (listening endpoint stays open).
281 run_event_loop (u_short port
)
283 // Raise the socket handle limit to the maximum.
284 ACE::set_handle_limit ();
286 // Create the oneway and twoway acceptors.
287 ACE_SOCK_Acceptor twoway_acceptor
;
288 ACE_SOCK_Acceptor oneway_acceptor
;
290 // Create the oneway and twoway server addresses.
291 ACE_INET_Addr
twoway_server_addr (port
);
292 ACE_INET_Addr
oneway_server_addr (port
+ 1);
294 // Create acceptors, reuse the address.
295 if (twoway_acceptor
.open (twoway_server_addr
, 1) == -1
296 || oneway_acceptor
.open (oneway_server_addr
, 1) == -1)
297 ACE_ERROR_RETURN ((LM_ERROR
,
301 // Check to see what addresses we actually got bound to!
302 else if (twoway_acceptor
.get_local_addr (twoway_server_addr
) == -1
303 || oneway_acceptor
.get_local_addr (oneway_server_addr
) == -1)
304 ACE_ERROR_RETURN ((LM_ERROR
,
309 ACE_DEBUG ((LM_DEBUG
,
310 "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
311 twoway_server_addr
.get_port_number (),
312 oneway_server_addr
.get_port_number ()));
314 // Keep these objects out here to prevent excessive constructor
315 // calls within the loop.
316 ACE_SOCK_Stream new_stream
;
318 ACE_Handle_Set handle_set
;
319 handle_set
.set_bit (twoway_acceptor
.get_handle ());
320 handle_set
.set_bit (oneway_acceptor
.get_handle ());
322 // Performs the iterative server activities.
326 ACE_Time_Value
timeout (ACE_DEFAULT_TIMEOUT
);
327 ACE_Handle_Set temp
= handle_set
;
329 int result
= ACE_OS::select (ACE_Utils::truncate_cast
<int> ((intptr_t)oneway_acceptor
.get_handle ()) + 1,
335 ACE_ERROR ((LM_ERROR
,
338 else if (result
== 0 && verbose
)
339 ACE_DEBUG ((LM_DEBUG
,
340 "(%P|%t) select timed out\n"));
343 if (temp
.is_set (twoway_acceptor
.get_handle ()))
345 if (twoway_acceptor
.accept (new_stream
) == -1)
347 ACE_ERROR ((LM_ERROR
,
353 ACE_DEBUG ((LM_DEBUG
,
354 "(%P|%t) spawning twoway server\n"));
356 // Run the twoway server.
357 run_server (twoway_server
,
358 new_stream
.get_handle ());
360 if (temp
.is_set (oneway_acceptor
.get_handle ()))
362 if (oneway_acceptor
.accept (new_stream
) == -1)
364 ACE_ERROR ((LM_ERROR
, "%p\n", "accept"));
368 ACE_DEBUG ((LM_DEBUG
,
369 "(%P|%t) spawning oneway server\n"));
371 // Run the oneway server.
372 run_server (oneway_server
,
373 new_stream
.get_handle ());
382 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
384 u_short port
= ACE_DEFAULT_SERVER_PORT
;
387 port
= ACE_OS::atoi (argv
[1]);
389 return run_event_loop (port
);