2 //=============================================================================
4 * @file SOCK_Send_Recv_Test.cpp
6 * This is a test of the <ACE_SOCK>'s various send and receive
7 * methods. The test forks two processes or spawns two threads
8 * (depending upon the platform) and then executes client and
9 * server allowing them to connect and exchange data in ways
10 * designed to exercise the send and recv functions.
12 * Right now, it primarily tests the iov-like send and recv
13 * functions, but others should be added to completely cover the
16 * @author Steve Huston <shuston@riverace.com>
18 //=============================================================================
21 #include "test_config.h"
22 #include "ace/OS_NS_sys_wait.h"
23 #include "ace/OS_NS_unistd.h"
24 #include "ace/Thread.h"
25 #include "ace/Thread_Manager.h"
26 #include "ace/Time_Value.h"
27 #include "ace/SOCK_Connector.h"
28 #include "ace/SOCK_Acceptor.h"
29 #include "ace/SOCK_Stream.h"
33 // Change to non-zero if test fails
34 static int Test_Result
= 0;
36 #if !defined (ACE_LACKS_FORK) || defined (ACE_HAS_THREADS)
38 // In test 3, a large amount of data is sent. The purpose is to overflow the
39 // TCP send window, causing the sender to block (it's a send_n). This value
40 // is the amount to send. The assumption is that no implementation has a
41 // receive window larger than 128K bytes. If one is found, this is the place
43 // For some odd reason, NT will try to send a single large buffer, but not
44 // multiple smaller ones that add up to the large size.
45 const size_t Test3_Send_Size
= 4*1024;
46 const size_t Test3_Loops
= 10;
47 const size_t Test3_Total_Size
= Test3_Send_Size
* Test3_Loops
;
53 ACE_INET_Addr
*remote_addr
= reinterpret_cast<ACE_INET_Addr
*> (arg
);
54 ACE_INET_Addr
server_addr (remote_addr
->get_port_number (),
56 ACE_SOCK_Stream cli_stream
;
57 ACE_SOCK_Connector con
;
58 ACE_Time_Value
timeout (ACE_DEFAULT_TIMEOUT
);
61 ACE_TEXT ("(%P|%t) Connecting to port %d\n"),
62 server_addr
.get_port_number()));
64 // Initiate connection with server; don't wait forever
65 if (con
.connect (cli_stream
,
70 ACE_TEXT ("(%P|%t) %p\n"),
71 ACE_TEXT ("connection failed")));
77 ACE_TEXT ("(%P|%t) connected to %C\n"),
78 server_addr
.get_host_name ()));
80 //******************* TEST 0 ******************************
82 // First make sure that non-blocking receive works as intended.
83 // Set the socket to non-blocking and do a recv() - the server side
84 // will send a short piece of data after sleeping for a few seconds.
85 // This means we should get a EWOULDBLOCK first; then change to
86 // blocking for the rest of the tests.
92 if (-1 == cli_stream
.enable (ACE_NONBLOCK
))
94 ACE_TEXT ("(%P|%t) %p\n"),
95 ACE_TEXT ("Can't enable test 0 nonblocking")));
97 len
= cli_stream
.recv (buffer
, sizeof (buffer
));
98 cli_stream
.disable (ACE_NONBLOCK
);
101 if (errno
== EWOULDBLOCK
)
102 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) Nonblocking recv ok!\n")));
105 ACE_ERROR ((LM_ERROR
,
106 ACE_TEXT ("(%P|%t) %p\n"),
107 ACE_TEXT ("Nonblocking recv")));
110 cli_stream
.recv (buffer
, sizeof (buffer
)); // Drain the sent data
114 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) Nonblocking recv blocked\n")));
118 //******************* TEST 1 ******************************
120 // Do a iovec sendv - send the 255 byte buffer in 5 chunks. The
121 // server will verify that the correct data is sent, and that there
122 // is no more and no less.
124 // The server will verify that this data pattern gets there intact.
126 for (i
= 0; i
< sizeof buffer
; ++i
)
127 buffer
[i
] = static_cast<u_char
> (i
);
131 iov
[0].iov_base
= reinterpret_cast<char *> (&buffer
[0]);
134 iov
[1].iov_base
= reinterpret_cast<char *> (&buffer
[50]);
137 iov
[2].iov_base
= reinterpret_cast<char *> (&buffer
[75]);
138 iov
[2].iov_len
= 150;
140 iov
[3].iov_base
= reinterpret_cast<char *> (&buffer
[225]);
143 iov
[4].iov_base
= reinterpret_cast<char *> (&buffer
[254]);
146 len
= cli_stream
.sendv (iov
, 5);
149 ACE_ERROR ((LM_ERROR
,
150 ACE_TEXT ("(%P|%t) %p\n"),
151 ACE_TEXT ("Test 1, sendv failed")));
155 ACE_ERROR ((LM_ERROR
,
156 ACE_TEXT ("(%P|%t) test 1 recvd %d; should be 255\n"),
157 static_cast<int> (len
)));
159 //******************* TEST 2 ******************************
161 // The same data is coming back - receive it using recv (size_t n,
162 // ...) and compare it to the original data.
165 // Give it a chance to get here
167 #ifndef ACE_LACKS_VA_FUNCTIONS
168 len
= cli_stream
.recv (4,
176 ACE_ERROR ((LM_ERROR
,
177 ACE_TEXT ("(%P|%t) %m; len is %d, but should be 255!\n"),
181 for (i
= 0; i
< 255; i
++)
182 if (buffer2
[i
] != buffer
[i
])
184 ACE_ERROR ((LM_ERROR
,
185 ACE_TEXT ("(%P|%t) Test 2, rcvd byte %d is %d, not %d\n"),
186 i
, buffer2
[i
], buffer
[i
]));
190 //******************* TEST 3 ******************************
192 // Do a send_n of a large size. The receive should sleep some to
193 // cause the data reception to be delayed, which will fill up the
194 // TCP window and cause send_n to block at some point. The particular
195 // case this tests only needs to be exercised if the socket is
196 // non-blocking, so set that first.
198 char buff
[Test3_Send_Size
];
199 if (-1 == cli_stream
.enable (ACE_NONBLOCK
))
200 ACE_ERROR ((LM_ERROR
,
201 ACE_TEXT ("(%P|%t) %p\n"),
202 ACE_TEXT ("Can't enable test 3 nonblocking")));
203 for (i
= 0; i
< Test3_Loops
; ++i
)
206 ssize_t sent
= cli_stream
.send_n (buff
, sizeof (buff
));
207 if (sent
!= (ssize_t
) sizeof (buff
) && errno
!= 0)
209 ACE_ERROR ((LM_ERROR
,
210 ACE_TEXT ("(%P|%t) Test 3, pass %d, sent %d, %p\n"),
211 i
, sent
, ACE_TEXT ("error")));
212 Test_Result
= 1; // Fail
224 ACE_SOCK_Acceptor
*peer_acceptor
= (ACE_SOCK_Acceptor
*) arg
;
225 ACE_SOCK_Stream sock_str
;
226 ACE_INET_Addr cli_addr
;
227 ACE_Time_Value
timeout (ACE_DEFAULT_TIMEOUT
);
229 // Accept the connection over which the stream tests will run.
230 // Don't lock up if client doesn't connect
231 if (peer_acceptor
->accept (sock_str
,
235 ACE_ERROR ((LM_ERROR
,
236 ACE_TEXT ("(%P|%t) %p\n"),
237 ACE_TEXT ("accept")));
242 ACE_DEBUG ((LM_DEBUG
,
243 ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
244 cli_addr
.get_host_name (),
245 cli_addr
.get_port_number ()));
247 //******************* TEST 1 ******************************
249 // The client will be expecting to not see data for a few seconds.
250 // Wait a bit then send a short blurb to complete the client's recv.
253 sock_str
.send ("abc", 3);
255 //******************* TEST 1 ******************************
257 // Do a iovec recvv - the client should send 255 bytes, which we
258 // will be detected and read into a ACE-allocated buffer. Use a 5
259 // second timeout to give the client a chance to send it all.
268 iov
[0].iov_base
= reinterpret_cast<char *> (&buffer
[0]);
271 iov
[1].iov_base
= reinterpret_cast<char *> (&buffer
[75]);
272 iov
[1].iov_len
= 100;
274 iov
[2].iov_base
= reinterpret_cast<char *> (&buffer
[175]);
277 len
= sock_str
.recvv_n (iov
, 3);
280 ACE_ERROR ((LM_ERROR
,
281 ACE_TEXT ("(%P|%t) %p\n"),
282 ACE_TEXT ("Test 1, recvv failed")));
288 ACE_ERROR ((LM_ERROR
,
289 ACE_TEXT ("(%P|%t) Test 1 recvd %d; should be 255\n"),
290 static_cast<int> (len
)));
293 for (i
= 0; i
< 255; i
++)
296 ACE_ERROR ((LM_ERROR
,
297 ACE_TEXT ("(%P|%t) Test 1, rcvd byte %d is %d, not %d\n"),
304 //******************* TEST 2 ******************************
306 // Send the buffer back, using send (size_t n, ...) in 3 pieces.
308 #ifndef ACE_LACKS_VA_FUNCTIONS
309 len
= sock_str
.send (6,
320 ACE_ERROR ((LM_ERROR
,
321 ACE_TEXT ("(%P|%t) Test 2 sent %d; should be 255\n"),
322 static_cast<int> (len
)));
326 //******************* TEST 3 ******************************
328 // The sender is testing send_n to make sure it blocks if the TCP
329 // window fills. So sleep here for a bit to avoid getting the data
330 // yet. Then just read and empty out the received data.
332 // Keep reading until the peer closes.
333 sock_str
.disable (ACE_NONBLOCK
);
335 size_t total_recv
= 0;
339 got
= sock_str
.recv (buffer
, sizeof (buffer
));
345 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) Test 3 received %d bytes\n"),
348 if (total_recv
== Test3_Total_Size
)
350 if (got
!= 0 || errno
!= 0)
352 ACE_ERROR ((LM_ERROR
,
353 ACE_TEXT ("(%P|%t) Test 3 final recv status %d, expected 0\n"),
355 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"),
356 ACE_TEXT ("expected errno == 0, instead")));
357 Test_Result
= 1; // Fail
362 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) Test 3 expected %d %p\n"),
363 Test3_Total_Size
, ACE_TEXT ("bytes")));
372 #endif /* !ACE_LACKS_FORK || ACE_HAS_THREADS */
378 ACE_SOCK_Acceptor peer_acceptor
;
380 // Create a server address.
381 ACE_INET_Addr server_addr
;
383 // Bind listener to any port and then find out what the port was.
384 if (peer_acceptor
.open (ACE_Addr::sap_any
) == -1
385 || peer_acceptor
.get_local_addr (server_addr
) == -1)
386 ACE_ERROR ((LM_ERROR
,
387 ACE_TEXT ("(%P|%t) %p\n"),
391 ACE_DEBUG ((LM_DEBUG
,
392 ACE_TEXT ("(%P|%t) starting server at port %d\n"),
393 server_addr
.get_port_number ()));
395 #if !defined (ACE_LACKS_FORK)
396 switch (ACE_OS::fork (ACE_TEXT ("child")))
399 ACE_ERROR ((LM_ERROR
,
400 ACE_TEXT ("(%P|%t) %p\n%a"),
401 ACE_TEXT ("fork failed"),
405 ACE_LOG_MSG
->sync (ACE_TEXT ("SOCK_Send_Recv_Test-child"));
406 client (&server_addr
);
410 server (reinterpret_cast<void *> (&peer_acceptor
));
411 ACE_OS::waitpid (0, 0, 0);
413 #elif defined (ACE_HAS_THREADS)
414 if (ACE_Thread_Manager::instance ()->spawn
415 (ACE_THR_FUNC (server
),
416 reinterpret_cast<void *> (&peer_acceptor
),
417 THR_NEW_LWP
| THR_DETACHED
) == -1)
418 ACE_ERROR ((LM_ERROR
,
419 ACE_TEXT ("(%P|%t) %p\n%a"),
420 ACE_TEXT ("thread create failed"),
423 if (ACE_Thread_Manager::instance ()->spawn
424 (ACE_THR_FUNC (client
),
425 reinterpret_cast<void *> (&server_addr
),
426 THR_NEW_LWP
| THR_DETACHED
) == -1)
427 ACE_ERROR ((LM_ERROR
,
428 ACE_TEXT ("(%P|%t) %p\n%a"),
429 ACE_TEXT ("thread create failed"),
432 // Wait for the threads to exit.
433 ACE_Thread_Manager::instance ()->wait ();
436 ACE_TEXT ("(%P|%t) ")
437 ACE_TEXT ("only one thread may be run ")
438 ACE_TEXT ("in a process on this platform\n")));
439 #endif /* ACE_HAS_THREADS */
441 peer_acceptor
.close ();
446 run_main (int, ACE_TCHAR
*[])
448 ACE_START_TEST (ACE_TEXT ("SOCK_Send_Recv_Test"));
450 #ifndef ACE_LACKS_ACCEPT