summaryrefslogtreecommitdiff
path: root/examples/IPC_SAP/SOCK_SAP/CPP-inserver.cpp
blob: 313d1c683b6cd666830e03251c93a4b08220290f (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
138
139
140
141
142
143
144
145
146
147
148
149
150
// This example tests the non-blocking features of the
// ACE_SOCK_Acceptor and ACE_SOCK_Stream classes.
// $Id$


#include "ace/SOCK_Acceptor.h"                             
#include "ace/SOCK_Stream.h"
#include "ace/INET_Addr.h"
#include "ace/Handle_Set.h"

// ACE SOCK_SAP server. 

int 
main (int argc, char *argv[])
{                                                                
  u_short port = argc > 1 
    ? ACE_OS::atoi (argv[1]) 
    : ACE_DEFAULT_SERVER_PORT;
  ACE_Time_Value timeout (argc > 2 
			  ? ACE_OS::atoi (argv[2]) 
			  : ACE_DEFAULT_TIMEOUT);
  int sleep_time = argc > 3 ? ACE_OS::atoi (argv[3]) : 0;
    
  ACE_SOCK_Acceptor peer_acceptor;

  // Create a server address.
  ACE_INET_Addr server_addr (port);

  // Create a server, reuse the address.
  if (peer_acceptor.open (server_addr, 1) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 1);
#if !defined(VXWORKS)
  // Set the peer acceptor into non-blocking mode.
  else if (peer_acceptor.enable (ACE_NONBLOCK) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "enable"), 1);
#endif /* !VXWORKS */
  else if (peer_acceptor.get_local_addr (server_addr) == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "get_local_addr"), 1);

  ACE_DEBUG ((LM_DEBUG, "starting server at port %d\n",
	      server_addr.get_port_number ()));

  // Keep these objects out here to prevent excessive constructor
  // calls within the loop.
  ACE_SOCK_Stream new_stream;                                   
  ACE_INET_Addr cli_addr;
  ACE_Handle_Set handle_set;

  // Performs the iterative server activities.

  for (;;) 
    {
      char buf[BUFSIZ];                                     
                                                                     
      handle_set.reset ();
      handle_set.set_bit (peer_acceptor.get_handle ());

      int result = ACE_OS::select (int (peer_acceptor.get_handle ()) + 1,
				   handle_set,
				   0, 0, timeout);
      if (result == -1)
	ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "select"), -1);
      else if (result == 0)
	ACE_DEBUG ((LM_DEBUG, "select timed out\n"));
      else
	{
	  // Create a new ACE_SOCK_Stream endpoint (note automatic restart
	  // if errno == EINTR). 
      
	  while ((result = peer_acceptor.accept (new_stream, &cli_addr)) != -1)
	    {
	      ACE_DEBUG ((LM_DEBUG, "client %s connected from %d\n", 
			  cli_addr.get_host_name (), cli_addr.get_port_number ()));
      
#if !defined(VXWORKS)
	      // Enable non-blocking I/O.
	      if (new_stream.enable (ACE_NONBLOCK) == -1)
		ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "enable"), -1);
#endif /* !VXWORKS */
	  
	      handle_set.reset ();
	      handle_set.set_bit (new_stream.get_handle ());
	  
	      // Read data from client (terminate on error).
	  
	      for (ssize_t r_bytes;;)
		{
		  // Wait to read until there's something from the client.
		  if (ACE_OS::select (int (new_stream.get_handle ()) + 1,
				      handle_set,
				      0, 0, timeout) == -1)
		    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "select"), -1);
	      
		  // Keep reading until the client shuts down.
		  for (;;)
		    {
		      // Sleep for some amount of time in order to
		      // test client flow control.
		      ACE_OS::sleep (sleep_time);

		      r_bytes = new_stream.recv (buf, sizeof buf, 0, &timeout);

		      if (r_bytes <= 0)
			{
			  if (errno == ETIME)
			    ACE_ERROR ((LM_ERROR, "%p\n", "ACE::recv"));
			  break;
			}
		      else if (ACE::write_n (ACE_STDOUT, buf, r_bytes) != r_bytes)
			ACE_ERROR ((LM_ERROR, "%p\n", "ACE::send_n"));
		    }

		  if (r_bytes == 0)
		    {
		      ACE_DEBUG ((LM_DEBUG, 
				  "reached end of input, connection closed by client\n"));

		      // Send handshake back to client to unblock it.
		      if (new_stream.send_n ("", 1) != 1)
			ACE_ERROR ((LM_ERROR, "%p\n", "send_n"));
		      break;
		    }
		  else if (r_bytes == -1)
		    {
		      if (errno == EWOULDBLOCK || errno == ETIME)
			ACE_DEBUG ((LM_DEBUG, 
				    "no input available, going back to reading\n"));
		      else
			ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv"), -1);
		    }
		}

	      // Close new endpoint (listening endpoint stays open).
	      if (new_stream.close () == -1) 
		ACE_ERROR ((LM_ERROR, "%p\n", "close"));
	    }

	  if (result == -1)
	    {
	      if (errno == EWOULDBLOCK)
		ACE_DEBUG ((LM_DEBUG, 
			    "no connections available, going back to accepting\n"));
	      else
		ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE::write"), -1);
	    }
	}
    }
  /* NOTREACHED */
  return 0;
}