Trying to fix a Segmentation Fault with multi-threading TCP Listener
I have a basic idea of what is causing the Segmentation Faul (essentially accessing memory that I'm not allowed to) when I try to run the program from the command line. While debugging the code through Eclipse it works okay without complaining. I have a server that needs to accept streamed tcp data from N different machines. The number of allowable connections is established by the two arguments provided at runtime, which are two port numbers that establish a range that the server will be listening on. I then am creating a thread for each port within that range which then dumps any data received to the console. I understand that this code is hideous at best, but I'm just trying to make it work before building in the argument validation and better error handling. Hideous Code: Code:
#include <iostream> #include <netinet/in.h> #include <netdb.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> using namespace std; // Declare a global variable that we can use to let us know we need // to exit this program. volatile bool KeepRunning = true; void error(const char *msg) { perror(msg); exit(0); } void *ListenForConnection(void *ptr); // Declare a structure that we can use to pass in any information // into the thread we are going to kick off. If any new parameters // are needed simply add them to this "struct" object and they will // be available within the method that is called via the thread. struct tcp_connection_params { // This is the port number to use int tcp_port; }; int main(int argc, char *argv[]) { // Take the second parameter as our starting port number int from_port = atoi(argv[1]); // The third parameter will be our ending port number int to_port = atoi(argv[2]); // This variable will be used to help us identify how many // threads we will be needing to create int ThreadCount = to_port - from_port; // Create an array of threads, but we can't specify // how many threads we will need just yet pthread_t *Thread_Array; // Declare a tcp_connection_params object that we will use to pass in // our parameters when we create a new thread. struct tcp_connection_params params; // We need to base our number of threads upon how many // ports we were told to open Thread_Array = new pthread_t[ThreadCount + 1]; // Now that we have our array of threads identified // we can run through a loop of that amount creating // new threads dedicated to listening on the specified // port number. for (int i=0; i <= ThreadCount; i++) { pthread_create(&(Thread_Array[i]), NULL, &ListenForConnection, ¶ms); params.tcp_port = from_port + i; } // Make sure we wait for all of the threads to finish // working before we exit the program for (int i = 0; i <= ThreadCount; i++) { pthread_join(Thread_Array[i], NULL); } return 0; } void *ListenForConnection(void* parameters) { // This will be used to open the original socket on the // designated port. int socket_file_descriptor; // At which point we will move that connection over to another // port which will be saved in this variable. int new_socket_file_descriptor; // This variable will be used to count the number of characters // that are sent from the remote system. int n; // This is an easier way for us to identify which port we will // be using to bind to the socket. int port_number; // We need to create a boolean value stored as an integer so // that we can reuse a socket once communication has finished. int yes = 1; struct sockaddr_in server_address; struct sockaddr_in client_address; // Here is where we will store our message char buffer[256]; // create a pointer to a tcp_connection_params object so that // we can reference any parameters that we passed into this // method. struct tcp_connection_params* pp = (struct tcp_connection_params*) parameters; port_number = pp->tcp_port; socklen_t client_length; socket_file_descriptor = socket(AF_INET, SOCK_STREAM, 0); if (socket_file_descriptor < 0) { error("Error Opening Socket"); } else { // Make sure that we can reuse the sockets once the filler // has closed the connection. setsockopt(socket_file_descriptor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); // Clear the buffer used for the server's address bzero((char *) &server_address, sizeof(server_address)); // Now that we have cleared that buffer we can populate // it with our new data server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = INADDR_ANY; server_address.sin_port = htons(port_number); if (bind(socket_file_descriptor, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { char* p; string Crap("ERROR binding to socket on port number:" + port_number); p = new char[Crap.size() + 1]; strcpy(p, Crap.c_str()); error("ERROR binding to socket"); } else { listen(socket_file_descriptor, 5); client_length = sizeof(client_address); while(KeepRunning) { setsockopt(new_socket_file_descriptor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); new_socket_file_descriptor = accept(socket_file_descriptor, (struct sockaddr *) & client_address, &client_length); n = read(new_socket_file_descriptor, buffer, 255); if (n > 0) { if (buffer[0] == 'A') KeepRunning = false; printf(buffer); } close(new_socket_file_descriptor); } } close(socket_file_descriptor); } close(new_socket_file_descriptor); close(socket_file_descriptor); return NULL; } I'm wondering if the Segmentation Fault is due to me not allocating and de-allocating memory for the threads. Would that cause my error? Thanks in advance. |
No comments:
Post a Comment