Linux Sockets and POSIX threads example

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • dariophoenix
    New Member
    • Oct 2006
    • 34

    Linux Sockets and POSIX threads example

    Hi,
    I am trying to encapsulate Linux sockets and POSIX threads in C++ classes (I work in Knoppix, using KDevelop). Since sockets and threads are new to me, I searched for example code and found the following:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <netdb.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <netinet/ip.h>
    #include <pthread.h>
    
    struct sockaddr_in getipa(const char*, int);
    void printerror(const char*);
    
    void* runclient(void*);
    void* runserver(void*);
    
    int main(){
    	pthread_t server;
    	pthread_t client;
    
    	if(pthread_create(&server, NULL, runserver, NULL) != 0){
    		puts("Could not create server thread");
    
    		return EXIT_FAILURE;
    	}
    
    	if(pthread_create(&client, NULL, runclient, NULL) != 0){
    		puts("Could not create client thread");
    
    		return EXIT_FAILURE;
    	}
    
    	pthread_join(server, NULL);
    	pthread_join(client, NULL);
    
    	return EXIT_SUCCESS;
    }
    
    struct sockaddr_in getipa(const char* hostname, int port){
    	struct sockaddr_in ipa;
    	ipa.sin_family = AF_INET;
    	ipa.sin_port = htons(port);
    
    	struct hostent* localhost = gethostbyname(hostname);
    	if(!localhost){
    		printerror("resolveing localhost");
    
    		return ipa;
    	}
    
    	char* addr = localhost->h_addr_list[0];
    	memcpy(&ipa.sin_addr.s_addr, addr, sizeof addr);
    
    	return ipa;
    }
    
    void printerror(const char* action){
    	int errnum = errno;
    	errno = 0;
    
    	if(errnum > 0){
    		printf("An error occured while %s.nError code: %inError description: %sn",
    				action, errnum, strerror(errnum));
    	}else if(h_errno > 0){
    		printf("An error occured while %s.nError code: %inError description: %sn",
    				action, h_errno, hstrerror(h_errno));
    
    		h_errno = 0;
    	}else{
    		printf("An error occured while %s.n There is no error data.n", action);
    	}
    }
    
    void* runserver(void* context){
    	struct protoent* tcp;
    	tcp = getprotobyname("tcp");
    
    	int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
    	if(sfd == -1){
    		printerror("createing a tcp socket");
    
    		return NULL;
    	}
    
    	struct sockaddr_in isa = getipa("localhost", 1025);
    
    	if(bind(sfd, (struct sockaddr*)&isa, sizeof isa) == -1){
    		printerror("binding socket to IP address");
    
    		return NULL;
    	}
    
    	if(listen(sfd, 1) == -1){
    		printerror("setting socket to listen");
    
    		return NULL;
    	}
    
    	int cfd = accept(sfd, NULL, NULL);
    
    	if(cfd == -1){
    		if(errno == EAGAIN || errno == EWOULDBLOCK){
    			puts("SIGIO recieved for listen socket, but don't know why.");
    		}else{
    			printerror("accepting a connection");
    
    			return NULL;
    		}
    	}
    
    	char msg[] = "Message to be sent";
    
    	if(send(cfd, (void*) msg, sizeof msg, MSG_NOSIGNAL) == -1){
    		printerror("sending message to client");
    	}
    
    	shutdown(cfd, SHUT_RDWR);
    
    	return NULL;
    }
    
    void* runclient(void* context){
    	struct protoent* tcp;
    	tcp = getprotobyname("tcp");
    
    	int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
    	if(sfd == -1){
    		printerror("createing a tcp socket");
    
    		return NULL;
    	}
    
    	struct sockaddr_in isa = getipa("localhost", 1025);
    
    	if(connect(sfd, (struct sockaddr*)&isa, sizeof isa) == -1){
    		printerror("connecting to server");
    
    		return NULL;
    	}
    
    	char buff[255];
    	ssize_t size = recv(sfd, (void*)buff, sizeof buff, MSG_WAITALL);
    
    	if(size == -1){
    		printerror("recieving data from server");
    	}else{
    		buff[size] = '';
    
    		puts(buff);
    	}
    
    	shutdown(sfd, SHUT_RDWR);
    
    	return NULL;
    }
    This is C code, but I thought, "If I get this working, encapsulating in classes will be easy". The problem is that this code works fine only the first run; afterwards, it cannot resolve the IP address. Which could be the reason?
  • dariophoenix
    New Member
    • Oct 2006
    • 34

    #2
    I discovered that changing the port number and recompiling allows for another succesful run (only once, like before). Therefore, it seems to me that ports are not freed after the program finishes. How can I do that?

    Comment

    • dariophoenix
      New Member
      • Oct 2006
      • 34

      #3
      Well, I figured it out myself: Even if you close a socket correctly, it takes a maximum of 60 seconds for it to be freed: I ran the first time OK; then I waited a minute, ran again and had no problems. So that's it, I hope this helps someone.

      Comment

      Working...