source: fact/tools/FAD/SocketFunctions/SocketFunctions.cpp@ 15018

Last change on this file since 15018 was 9887, checked in by neise, 14 years ago
added 'fadfake' a programm acting as a FAD board. still with very limited funcionality, but nice for testing... added a function OpenServerSocket() to SocketFunctions.cpp
File size: 9.0 KB
Line 
1#include <sys/socket.h>
2#include <arpa/inet.h>
3#include <cstdlib>
4#include <time.h>
5#include <sys/time.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <stdio.h>
9
10#include "SocketFunctions.h"
11
12/*
13OpenSockets opens NumberOfSockets TCP Sockets.
14a pointer to an array of SocketDescriptors is returned.
15In case of error, the NULL pointer is returned.
16
17In order to Close the Sockets and free memory call
18void CloseSockets(int * SocketDescriptors, unsigned int NumberOfSockets);
19*/
20
21int * OpenSockets(unsigned int NumberOfSockets){
22int verbose=0;
23
24if (verbose)
25
26 if (NumberOfSockets < 1) {
27 fprintf ( stderr,
28 "Error: OpenSockets was called with a NumberOfSockets = %d.\n",
29 NumberOfSockets );
30 return NULL;
31 }
32 if (NumberOfSockets > MAX_NUMBER_OF_OPENED_TCP_SOCKETS) {
33 fprintf ( stderr,
34 "Warning: OpenSockets was called with a NumberOfSockets = %d.\n",
35 NumberOfSockets );
36 return NULL;
37 }
38
39 int *SocketDescriptor;
40 if (verbose) fprintf (stderr, "malloc\n");
41 SocketDescriptor = (int *) malloc( NumberOfSockets * sizeof(int) );
42 if (verbose) fprintf (stderr, "after malloc\n");
43 // what if malloc was not able to get enough memory?
44 // error chekc missing here
45 // TODO
46
47 for (unsigned int i = 0; i < NumberOfSockets; i++) {
48 if ((SocketDescriptor[i] = socket (PF_INET, SOCK_STREAM, 0)) == -1) {
49 //
50 // what does PF_INET and SOCK_STREAM stand for?
51 //
52 printf ("Error: Could not open socket Nr.: %d\n", i);
53 return NULL;
54 }
55 }
56 return SocketDescriptor;
57 if (verbose) printf ("end of OpenSockets\n");
58} // end of OpenSockets
59
60
61
62
63
64 /*
65 EmptySockets is used to read as much data from the TCP-Sockets in question
66 as possible. After waiting "timeout_usec" (default 125ms) -- see header file
67 without any data beeing present, the Socket is assumed to be empty.
68
69 Hopefully it is.
70
71 return is true if there was no error during the select statement.
72 false if select returned <0, which should not happen at all.
73 What to do if this happened?
74 */
75
76
77bool EmptySockets(int * SocketDescriptor, int NumberOfDescriptors, long timeout_usec){
78
79 fd_set Sockets; // select looks into this set, and checks which Sockets state changed
80 timeval timeout; // select needs a timeout to be deifned.
81 int max_fd=0; // select needs to know the maximum descriptor in fd_set Sockets.
82 int select_return; // used for debugging
83
84 unsigned char wastebin[WASTEBIN_SIZE]; // data ffrom sockets is dumped here
85
86 // find the maximum of SocketDescriptors
87 // needed by select() -- see man select
88
89
90 FD_ZERO (&Sockets);
91 for (int j = 0; j < NumberOfDescriptors; j++)
92 {
93 if (max_fd<SocketDescriptor[j]) {
94 max_fd = SocketDescriptor[j];
95 }
96 FD_SET (SocketDescriptor[j], &Sockets);
97 }
98 max_fd ++;
99
100 while (1){
101 timeout.tv_sec = 0;
102 timeout.tv_usec = timeout_usec;
103 select_return = select ( max_fd, &Sockets, NULL, NULL, &timeout);
104 if (select_return == 0) {
105 // none of the Sockets status changed
106 // nothing to read
107 break;
108 } else if (select_return <=0) {
109 return false; // this should never happen
110 fprintf(stderr, "error in EmptySockets: select returned %d abort. \n" , select_return);
111 } else { // select returned > 0
112 // now some Sockets might contain data
113 // it is checked for every Socket using: FD_ISSET
114 // then a pieces of WASTEBIN_SIZE chars is read out and discarded.
115 for (int j = 0; j < NumberOfDescriptors; j++) {
116 if (FD_ISSET (SocketDescriptor[j], &Sockets)){
117 read(SocketDescriptor[j], wastebin, WASTEBIN_SIZE);
118 }
119 }
120 //now every Socket, which had still some bytes, lost WASTEBIN_SIZE of it.
121 // still some might contain data -- so select is executed again.
122 }// end of else case: select returned > 0
123 } // end of while(1) loop -- jumped out if select returns 0
124return true;
125}
126
127/*
128 GetMaxFileDescriptor returns the value of the maximal
129 filedescriptor from NumberOfSockets SocketDescriptors.
130 The maximal filedescriptor + 1 is needed for select().
131*/
132
133int GetMaxFileDescriptor(unsigned int NumberOfSockets, int *SocketDescriptor){
134 int max_fd;
135 for (unsigned int i = 0; i < NumberOfSockets; i++)
136 {
137 if (SocketDescriptor[i] > max_fd)
138 {
139 max_fd = SocketDescriptor[i];
140 }
141 }
142 return max_fd;
143}
144
145
146
147
148/*
149Connect2Server connects NumberOfSockets TCP Sockets
150defined by SocketDescriptor
151to host defined by ServerIPaddress
152starting at Port StartPort, by adding 1 for each Socket
153
154return value is NumberOfSockets if successful
155it is zero if no Server was found and negative
156when connecting didn't work.
157The negative magnitude indicates which connection didn't work
158*/
159
160int Connect2Server( int *SocketDescriptor,
161 unsigned int NumberOfSockets,
162 unsigned int StartPort ,
163 char *ServerIPaddress ,
164 int verbose){
165
166 struct sockaddr_in SocketAddress[NumberOfSockets];
167 struct in_addr Serveripv4addr;
168
169 // Convert IP-Address to binary
170 if (inet_pton (AF_INET, ServerIPaddress, &Serveripv4addr) <= 0)
171 {
172 fprintf (stderr, "Error: network address not valid\n");
173 return 0;
174 }
175
176 if (verbose > 0) fprintf (stdout, "Trying to connect to %s...\n", ServerIPaddress);
177
178 for (unsigned int i = 0; i < NumberOfSockets; i++)
179 {
180 SocketAddress[i].sin_family = PF_INET;
181 SocketAddress[i].sin_port = htons ((unsigned short) StartPort + i);
182 SocketAddress[i].sin_addr = Serveripv4addr;
183
184 if (connect (SocketDescriptor[i], (struct sockaddr *) &SocketAddress[i], sizeof (SocketAddress[i])) == -1)
185 {
186 fprintf (stderr, "Error: Could not connect to server %s (port %d)\n", ServerIPaddress, StartPort + i);
187 return -i;
188 }
189 else if (verbose>0) {
190 printf ("Connected to %s:%d\n", ServerIPaddress, StartPort + i);
191 }
192 }
193
194 return NumberOfSockets;
195}
196
197/*
198CloseSockets closes NumberOfSockets TCP Sockets
199indicated by SocketDescriptor and frees the associated memory.
200*/
201int CloseSockets (int * SocketDescriptor ,
202 unsigned int NumberOfSockets)
203{
204 int close_return_val;
205 int return_val=0;
206
207 for (unsigned int i = 0; i < NumberOfSockets; i++)
208 {
209 if ( (close_return_val = close (SocketDescriptor[i])) != 0) {
210 fprintf (stderr, "Error: while trying to close SocketDescriptor[%d] = %d, close returned %d\n",
211 i ,
212 SocketDescriptor[i],
213 close_return_val );
214 return_val = close_return_val;
215 // no return close_return_val
216 // is performed here, because I want to try to close
217 // the other Ports before returning.
218 }
219 // ERRNO should better be checked and printed as well.
220 // TODO
221 }
222
223 return return_val;
224
225} // end of CloseSockets
226
227
228// returns Array of Sockethandles
229int * OpenServerSockets (unsigned int NumberOfSockets, unsigned int StartPort) {
230
231 // allocate memory for ServerSocket Descriptors
232// int ServerSocket[NumberOfSockets];
233 int *ServerSocket;
234 ServerSocket = (int *) malloc( NumberOfSockets * sizeof(int) );
235
236 // Create Sockets
237 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
238 if ((ServerSocket[i] = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
239 printf("Could not open server socket Nr. %d, no remote connection possible .\n", i);
240 return NULL;
241 }
242 }
243
244 // Allows immediate reuse of socket after closing (circumvents TIME_WAIT)
245 int Value=1;
246 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
247 if (setsockopt(ServerSocket[i], SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {
248 printf("Warning (ServerSocket Nr. %d): Could not set server socket option SO_REUSEADDR \n", i);
249 }
250 }
251
252 struct sockaddr_in SocketAddress[NumberOfSockets];
253 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
254 SocketAddress[i].sin_family = PF_INET;
255 SocketAddress[i].sin_port = htons((unsigned short) StartPort + i);
256 SocketAddress[i].sin_addr.s_addr = INADDR_ANY;
257 }
258
259
260 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
261 if (bind(ServerSocket[i], (struct sockaddr *) &SocketAddress[i], sizeof(SocketAddress[i])) == -1) {
262 printf("Could not bind port %d to socket Nr.: %d\n", StartPort+i, i );
263 close(ServerSocket[i]);
264 return NULL;
265 }
266 }
267
268 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
269 if (listen(ServerSocket[i], 0) == -1) {
270 printf("Could not set socket Nr. %d to listening \n", i);
271 close(ServerSocket[i]);
272 return NULL;
273 }
274 }
275
276 int *ConnectionSocket;
277 ConnectionSocket = (int *) malloc( NumberOfSockets * sizeof(int) );
278 struct sockaddr_in ClientAddress;
279 socklen_t SizeClientAddress=sizeof(ClientAddress);
280
281
282// while (1) { // Looping to wait for incoming connection
283 printf ("Waiting for connection...\n");
284 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
285 if ((ConnectionSocket[i] = accept(ServerSocket[i], (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1){
286 close(ServerSocket[i]);
287 return NULL;
288 }
289 }
290// }
291 for(unsigned int i=0 ; i < NumberOfSockets; i++ ){
292 // close(ServerSocket[i]);
293 }
294
295 printf("Connected to client at %s \n", inet_ntoa(ClientAddress.sin_addr));
296 return ConnectionSocket;
297} // end of OpenServerSockets
Note: See TracBrowser for help on using the repository browser.