#include #include #include #include #include #include #include #include #include "SocketFunctions.h" /* OpenSockets opens NumberOfSockets TCP Sockets. a pointer to an array of SocketDescriptors is returned. In case of error, the NULL pointer is returned. In order to Close the Sockets and free memory call void CloseSockets(int * SocketDescriptors, unsigned int NumberOfSockets); */ int * OpenSockets(unsigned int NumberOfSockets){ int verbose=0; if (verbose) if (NumberOfSockets < 1) { fprintf ( stderr, "Error: OpenSockets was called with a NumberOfSockets = %d.\n", NumberOfSockets ); return NULL; } if (NumberOfSockets > MAX_NUMBER_OF_OPENED_TCP_SOCKETS) { fprintf ( stderr, "Warning: OpenSockets was called with a NumberOfSockets = %d.\n", NumberOfSockets ); return NULL; } int *SocketDescriptor; if (verbose) fprintf (stderr, "malloc\n"); SocketDescriptor = (int *) malloc( NumberOfSockets * sizeof(int) ); if (verbose) fprintf (stderr, "after malloc\n"); // what if malloc was not able to get enough memory? // error chekc missing here // TODO for (unsigned int i = 0; i < NumberOfSockets; i++) { if ((SocketDescriptor[i] = socket (PF_INET, SOCK_STREAM, 0)) == -1) { // // what does PF_INET and SOCK_STREAM stand for? // printf ("Error: Could not open socket Nr.: %d\n", i); return NULL; } } return SocketDescriptor; if (verbose) printf ("end of OpenSockets\n"); } // end of OpenSockets /* EmptySockets is used to read as much data from the TCP-Sockets in question as possible. After waiting "timeout_usec" (default 125ms) -- see header file without any data beeing present, the Socket is assumed to be empty. Hopefully it is. return is true if there was no error during the select statement. false if select returned <0, which should not happen at all. What to do if this happened? */ bool EmptySockets(int * SocketDescriptor, int NumberOfDescriptors, long timeout_usec){ fd_set Sockets; // select looks into this set, and checks which Sockets state changed timeval timeout; // select needs a timeout to be deifned. int max_fd=0; // select needs to know the maximum descriptor in fd_set Sockets. int select_return; // used for debugging unsigned char wastebin[WASTEBIN_SIZE]; // data ffrom sockets is dumped here // find the maximum of SocketDescriptors // needed by select() -- see man select FD_ZERO (&Sockets); for (int j = 0; j < NumberOfDescriptors; j++) { if (max_fd 0 // now some Sockets might contain data // it is checked for every Socket using: FD_ISSET // then a pieces of WASTEBIN_SIZE chars is read out and discarded. for (int j = 0; j < NumberOfDescriptors; j++) { if (FD_ISSET (SocketDescriptor[j], &Sockets)){ read(SocketDescriptor[j], wastebin, WASTEBIN_SIZE); } } //now every Socket, which had still some bytes, lost WASTEBIN_SIZE of it. // still some might contain data -- so select is executed again. }// end of else case: select returned > 0 } // end of while(1) loop -- jumped out if select returns 0 return true; } /* GetMaxFileDescriptor returns the value of the maximal filedescriptor from NumberOfSockets SocketDescriptors. The maximal filedescriptor + 1 is needed for select(). */ int GetMaxFileDescriptor(unsigned int NumberOfSockets, int *SocketDescriptor){ int max_fd; for (unsigned int i = 0; i < NumberOfSockets; i++) { if (SocketDescriptor[i] > max_fd) { max_fd = SocketDescriptor[i]; } } return max_fd; } /* Connect2Server connects NumberOfSockets TCP Sockets defined by SocketDescriptor to host defined by ServerIPaddress starting at Port StartPort, by adding 1 for each Socket return value is NumberOfSockets if successful it is zero if no Server was found and negative when connecting didn't work. The negative magnitude indicates which connection didn't work */ int Connect2Server( int *SocketDescriptor, unsigned int NumberOfSockets, unsigned int StartPort , char *ServerIPaddress , int verbose){ struct sockaddr_in SocketAddress[NumberOfSockets]; struct in_addr Serveripv4addr; // Convert IP-Address to binary if (inet_pton (AF_INET, ServerIPaddress, &Serveripv4addr) <= 0) { fprintf (stderr, "Error: network address not valid\n"); return 0; } if (verbose > 0) fprintf (stdout, "Trying to connect to %s...\n", ServerIPaddress); for (unsigned int i = 0; i < NumberOfSockets; i++) { SocketAddress[i].sin_family = PF_INET; SocketAddress[i].sin_port = htons ((unsigned short) StartPort + i); SocketAddress[i].sin_addr = Serveripv4addr; if (connect (SocketDescriptor[i], (struct sockaddr *) &SocketAddress[i], sizeof (SocketAddress[i])) == -1) { fprintf (stderr, "Error: Could not connect to server %s (port %d)\n", ServerIPaddress, StartPort + i); return -i; } else if (verbose>0) { printf ("Connected to %s:%d\n", ServerIPaddress, StartPort + i); } } return NumberOfSockets; } /* CloseSockets closes NumberOfSockets TCP Sockets indicated by SocketDescriptor and frees the associated memory. */ int CloseSockets (int * SocketDescriptor , unsigned int NumberOfSockets) { int close_return_val; int return_val=0; for (unsigned int i = 0; i < NumberOfSockets; i++) { if ( (close_return_val = close (SocketDescriptor[i])) != 0) { fprintf (stderr, "Error: while trying to close SocketDescriptor[%d] = %d, close returned %d\n", i , SocketDescriptor[i], close_return_val ); return_val = close_return_val; // no return close_return_val // is performed here, because I want to try to close // the other Ports before returning. } // ERRNO should better be checked and printed as well. // TODO } return return_val; } // end of CloseSockets