Thread: I have a problem with basic socket programming using TCP

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    25

    I have a problem with basic socket programming using TCP

    This is my first project in a networks class. I am sorry if my code is attrocious, I'm still trying to wrap my head around socket programming.

    I have developed my client-server programs so that I can send messages to the server from multiple clients at once, utilizing detached threads to process all requests. This is no problem. The problem arises in the code to receive an echoed response from the server. I have it so that the server displays the message sent by the client, and this gets jumbled up, sort of like a data race. The echoed message the client gets is also jumbled in the same way. Printing only the buffer (Leaving the explanatory printf() out) works just fine with both the client and the server. My question is: why is my message getting interrupted every 3 characters?

    Thanks for reading.

    I hope I haven't left too many details out.

    Server:
    Code:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    
     static void *processRequest(void *);
    
    int main(int argc, char *argv[])
    {
    	int listenFeed, connectionFeed;
    
    	struct sockaddr_in servaddr;
    
    
        pthread_t tid;
    
    	listenFeed = socket(AF_INET, SOCK_STREAM, 0);
    
    	bzero(&servaddr, sizeof(servaddr));
    	servaddr.sin_family = AF_INET;
    	servaddr.sin_port = htons(8888);
    	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    	bind(listenFeed, (struct sockaddr *)&servaddr, sizeof(servaddr));
    	listen(listenFeed, 5);
    
    	for( ; ; ){
    		connectionFeed = accept(listenFeed, (struct sockaddr *) NULL, NULL);
    		pthread_create(&tid, NULL, &processRequest, &connectionFeed);
    	}
    }
    
    static void *processRequest(void *arg)
        {
    		size_t n;
            int     connectionFeed;
        	char buffer[4096];
            connectionFeed = * ((int *) arg);
            pthread_detach (pthread_self());
    
            bzero(buffer,sizeof(buffer));
    
        		while ( (n = read(connectionFeed, buffer, sizeof(buffer))) > 0){
        			printf("The message is below");     //<---- this printf gets displayed multiple times and jumbles the received message from the client.
        			printf("%s",buffer);
    
    				write(connectionFeed,buffer,n);
    				bzero(buffer,sizeof(buffer));
        		}
    
        		close(connectionFeed);
        		pthread_exit(0);
        		return (NULL);
        }
    And Client:
    Code:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int createSocket(char * serverName, int port, struct sockaddr_in * dest);
    int sendRequest(int sock, char * request, struct sockaddr_in * dest);
    int receiveResponse(int sock, char * response);
    
    int main(int argc, char *argv[])
    {
    	//Declare Variables
    	int     	socketFeed, port;
    	char    	buffer[4096];
    	struct  	sockaddr_in serverAddress;
    	struct  	sockaddr_in *serverAddressP;
    
    
    	port = 8888;
    	serverAddressP = &serverAddress; //For use in passing structure to arrays
    
    	//Create the socket and fill in first 3 fields of sockaddr_in structure, then connect to host
    	bzero(&serverAddress, sizeof(serverAddress));
    	socketFeed = createSocket(argv[1],port,serverAddressP);
    
    
    
    	for( ; ; ){
    		sendRequest(socketFeed, buffer, serverAddressP);
    		receiveResponse(socketFeed, buffer);
    	}
    	return 0;
    }
    
    int createSocket(char * serverName, int port, struct sockaddr_in * dest)
    {
    	int socketFeed;
    	socketFeed = socket(AF_INET, SOCK_STREAM, 0);
    	dest->sin_family = AF_INET;
    	dest->sin_port = htons(port);
    	inet_pton(AF_INET, serverName, &dest->sin_addr);
    	connect(socketFeed, (struct sockaddr *)&(*dest), sizeof(*dest));
    	return socketFeed;
    }
    
    int sendRequest(int sock, char * request, struct sockaddr_in * dest)
    {
    	bzero(request,sizeof(request));
    	fgets(request,sizeof(request),stdin);
    	write(sock, request, strlen(request));
    }
    
    int receiveResponse(int sock, char * response)
    {
    	bzero(response,sizeof(response));
    	read(sock,response,sizeof(response));     // <---- Troublesome code
    	printf("Echo of your message:\n");        // <----
    	printf("%s",response);                    // <---- Displays "Echo of your message\n" every 3 displayed characters of the response buffer
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > connectionFeed = accept(listenFeed, (struct sockaddr *) NULL, NULL);
    > pthread_create(&tid, NULL, &processRequest, &connectionFeed);
    You're passing a pointer to a local variable to each thread.
    So as you update the variable, each thread sees the change.

    > connectionFeed = * ((int *) arg);
    Yes, you make a copy, but it is still a hard to detect race condition.

    > bzero(response,sizeof(response));
    > read(sock,response,sizeof(response)); // <---- Troublesome code
    Now you're doing sizeof() on a POINTER

    You should really remove all your bzero() calls on all your char buffers.
    They're really not necessary at all, and are preventing you from learning how to do the right thing.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2011
    Posts
    25
    Hey. Sorry for the late response. I haven't been able to rid myself of my dependency of bzero() calls, but I have realized where I went wrong. It was in performing operations on response, a pointer.
    This is my new code which is a temporary workaround of the issue:
    Code:
    int sendRequest(int sock, char * request, struct sockaddr_in * dest)
    {
    	char request2[4096];
    	bzero(request2,sizeof(request2));
    	fgets(request2,sizeof(request2),stdin);
    	write(sock, request2, strlen(request2));
    }
    
    int receiveResponse(int sock, char * response)
    {
    	char response2[4096];
    	bzero(response2,sizeof(response2));
    	read(sock,response2,sizeof(response2));
    	printf("%s",response2);
    }
    I have tried to find out how to use sizeof() or strlen() with the passed pointer, but have not been successful so far. Does anyone have a preferred method for handling this? I'm not really supposed to change my function definition, so I can't pass more/fewer arguments to this function.

    Thanks again, Salem!

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Does anyone have a preferred method for handling this?
    Yes, you use the same method that fgets() uses, namely you pass in a parameter indicating the buffer size.

    But since you can't do that, you could assume a buffer size (say via a #define) in a small program such as this.

    fgets automatically appends a \0, so bzero is useless in this case.

    recv() returns a value indicating the amount of data stored, so appending a \0 yourself is very easy.
    Code:
    char buff[SIZE];
    n = recv( sock, buff, SIZE-1, 0 );   // or read(), same result either way
    if ( n > 0 ) {
      buff[n] = '\0';
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2011
    Posts
    25
    Thanks, that clears up alot and my issues are resolved (for anyone who may be reading this thread with a similar issue).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C Socket programming problem
    By jammiedodger in forum Networking/Device Communication
    Replies: 4
    Last Post: 10-30-2010, 01:35 PM
  2. Basic socket programming
    By cnewbie1 in forum C Programming
    Replies: 1
    Last Post: 03-28-2010, 05:10 PM
  3. Socket Programming Problem!!!!
    By bobthebullet990 in forum Networking/Device Communication
    Replies: 2
    Last Post: 02-21-2008, 07:36 PM
  4. Socket programming problem.
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 10-14-2002, 08:44 PM