Thread: select server writes message twice then hangs

  1. #1
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302

    select server writes message twice then hangs

    i have a few questions.
    one, if i use read like this
    Code:
    read(file_des, buffer, sizeof(buffer)-1);
    that will read from the buffer, x characters, and pad the rest with null terminators right?? Will that affect anything?

    second, what is the difference if i run the client this way: ./client 0.0.0.0 1234
    as to: ./client 127.0.0.1 1234

    third, i have a select server that MK27 helped me with. And i am compiling and running it, and i get the following. run server with ./select_server 1234 and it waits. I run the client, ./client 127.0.0.1 1234

    the client says,
    made connection to blah blah blah
    Message:

    i type in a message and server says,
    Server: got message: hey

    Server: got message: %
    then just hangs. i ran strace on the server and here are the results:
    Code:
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220o\1\0004\0\0\0"..., 512) = 512
    socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
    bind(3, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
    listen(3, 10)                           = 0
    select(1024, [3], NULL, NULL, NULL)     = 1 (in [3])
    accept(3, {sa_family=AF_INET, sin_port=htons(52858), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4
    read(4, "hey\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1023) = 1023
    write(1, "Server: got message: hey\n", 25Server: got message: hey
    ) = 25
    write(1, "\n", 1
    )                       = 1
    select(1024, [3 4], NULL, NULL, NULL)   = 1 (in [4])
    read(4, "K\201", 1023)                  = 2
    write(1, "Server: got message: K\201\n", 24Server: got message: K�
    ) = 24
    select(1024, [4], NULL, NULL, NULL)     = 1 (in [4])
    read(4, "", 1023)                       = 0
    write(2, "Exiting \n", 9Exiting 
    )               = 9
    Code:
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/select.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <signal.h>
    
    int read_from_client(int file_des) {
    	char buffer[1024];
    	int read_var;
    
            int i = sizeof(buffer)-1; if(i > 0) bzero(buffer, sizeof(buffer));
    	read_var = read(file_des, buffer, sizeof(buffer)-1);
    
    	if(read_var < 0) {
    		fprintf(stderr, "READ() error \n");
    		exit(1);
    	} else if(read_var == 0) {
    		 fprintf(stderr, "Exiting \n");
    		 exit(1);
    	}
    	else {
    		fprintf (stdout, "Server: got message: %s\n", buffer);
                    return 0;
    	}
    
    }
    
    int main(int argc, char *argv[]) {
    	int sockfd, newsockfd, portno, i;
    	socklen_t clilen;
    	struct sockaddr_in serv_addr, cli_addr;
    	fd_set read_fds;
    	int yes = 1;
    
    	if (argc < 2) fprintf(stderr, "No port provided ");
    
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);
    	if (sockfd < 0) {
    		fprintf(stderr, "Error creating socket  SOCKET()\n");
    		exit(1);
    	}
    
    	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
    		fprintf(stderr, "Address already in use  SETSOCKOPT()\n");
    		exit(1);
    	}
    
    	bzero((char *) &serv_addr, sizeof(serv_addr));
    	portno = atoi(argv[1]);
    	serv_addr.sin_family = AF_INET;
    	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    	serv_addr.sin_port = htons(portno);
    
    	if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
    		fprintf(stderr, "Error binding to socket  BIND()\n");
    		exit(1);
    	}
    
    	listen(sockfd, 10);
            clilen = sizeof(cli_addr);
    
    	FD_ZERO(&read_fds);
    	FD_SET(sockfd, &read_fds);
    
    	for( ; ; ) { /*1rst for loop*/
    		i = select(FD_SETSIZE, &read_fds, NULL, NULL, NULL); 
    		if (i < 0) { /*1rst if statement*/
    			fprintf(stderr, "Select server error  SELECT() %s\n", strerror(errno));
    			exit(1);
    		}
    		for (i = 0; i < 20; ++i) {  // should be high enough
    			if(FD_ISSET(i, &read_fds)) {
    				if(i == sockfd) {
    					newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    					if (newsockfd < 0) {
    						fprintf(stderr, "Error accepting new connection  ACCEPT() %s\n", strerror(errno));
    						exit(1);
    					}
    					FD_SET(newsockfd, &read_fds);
    				} else {
    					if(read_from_client (i) < 0) {
    						close(i);
    						FD_CLR(i, &read_fds);
    					}
    				}
    			}
    		}
    
       } 
    }
    thanks in advanced.

  2. #2
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    i fixed the printing twice problem. it seems that i had a newline char in the buffer.

    Code:
    int read_from_client(int file_des) {
    	char buffer[1024];
    	int read_var;
    
            bzero(buffer, sizeof(buffer));
    	read_var = read(file_des, buffer, sizeof(buffer));
    
    	if(read_var < 0) {
    		fprintf(stderr, "READ() error\n");
    		exit(1);
    	} else if(read_var == 0) {
    		 fprintf(stderr, "Exiting\n");
    		 exit(1);
    	}
    	else {
    		fprintf (stdout, "Client: %s\n", buffer);//Problematic newline char
                    //fix printf("Client: %s", buffer);
    		bzero(buffer, sizeof(buffer));
    		                
    	}
    	return 0;
    }
    It still hangs and for some reason the server opens 3 sockets when i run it. The first thing it does is read something thats already in the buffer...... I am stumped!!!

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > bzero(buffer, sizeof(buffer));
    > read_var = read(file_des, buffer, sizeof(buffer));
    The problem here, is that you don't guarantee a \0 in the buffer.
    If read completely fills the buffer, then you've lost.

    Just delete all those bzero calls, and go with
    Code:
    int read_from_client(int file_des) {
    	char buffer[1024];
    	int read_var;
    
            read_var = read(file_des, buffer, sizeof(buffer)-1);
    
    	if(read_var < 0) {
    		fprintf(stderr, "READ() error\n");
    		exit(1);
    	} else if(read_var == 0) {
    		 fprintf(stderr, "Exiting\n");
    		 exit(1);
    	}
    	else {
    		buffer[read_var] = '\0;
    		fprintf (stdout, "Client: %s\n", buffer);
    	}
    	return 0;
    }
    Note the -1 in the initial size calculation - this is to ensure there will always be space to add the \0.

    Perhaps you should post your send code as well.

    Have you used wireshark to monitor the actual network traffic?
    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.

  4. #4
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    here is the strace for the client

    Code:
    strace -v -e socket,connect,write,read ./client 127.0.0.1 1234
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220o\1\0004\0\0\0"..., 512) = 512 /*it already has 512 characters in the buffer.*/ 
    socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 /*Why is there 3 sockets created??*/
    read(4, "# Generated by NetworkManager\n", 4096) = 30
    read(4, "", 4096)                       = 0
    connect(3, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
    write(1, "Made a connection to 189.108.223"..., 35Made a connection to 189.108.223.0
    ) = 35
    write(1, "Message: ", 9Message: )                = 9
    read(0, ^C <unfinished ...>
    here is the strace for just the write function
    Code:
    annonymous@annonymous:~/Documents$ strace -e write ./client 127.0.0.1 1234
    write(1, "Made a connection to 189.140.214"..., 35Made a connection to 189.140.214.0
    ) = 35
    write(1, "Message: ", 9Message: )                = 9
    hey
    write(3, "hey\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1025) = 1025
    how are you //This is where it hangs.
    i fired up tcpdump and captured the the server and client in action. Then i used wireshark to open it.

    Code:
    LINE 1. 0.000000 127.0.0.1 127.0.0.1 TCP 49955 > italk [SYN] Seq=0 Win=32792 Len=0 MSS=16396 SACK_PERM=1 TSV=2945084 TSER=0 WS=6
    LINE 2.	0.000066 127.0.0.1 127.0.0.1 TCP italk > 49955 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=16396 SACK_PERM=1 TSV=2945085 TSER=2945084 WS=6
    LINE 3. 0.000115 127.0.0.1 127.0.0.1 TCP 49955 > italk [ACK] Seq=1 Ack=1 Win=32832 Len=0 TSV=2945085 TSER=2945085
    LINE 4.	7.516250 127.0.0.1 127.0.0.1 TCP 49955 > italk [PSH, ACK] Seq=1 Ack=1 Win=32832 Len=1025 TSV=2946964 TSER=2945085
    LINE 5. 7.516338 127.0.0.1 127.0.0.1 TCP italk > 49955 [ACK] Seq=1 Ack=1026 Win=34880 Len=0 TSV=2946964 TSER=2946964
    there were 3 more lines but after line 4 it wouldnt matter anyway.
    from what i see, the handshake is ok. No errors there.
    Then sends 1025 characters. 1 more than the sie of the buffer.

    another thing, after i close the server, the server does not return control to the client. Only when i close the server does control return to the client. The client will prompt me for a message to send to the server, 3 times in a row, then close too. Still cnnot figure out why the there are 3 file descriptors being created upon execution of the server.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Annonymous View Post
    another thing, after i close the server, the server does not return control to the client. Only when i close the server does control return to the client.
    That's totally contradictory, but it's not a big deal. You need to post your client code so we can run a full test on our end and help you debug. I'm about to call it a night, but I'll work on it in the morning if Salem or somebody else hasn't sorted it out by then.

  6. #6
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    correct me if i am wrong but read should return 0 when it receives a fin packet from the client, right? And it doesn't, as far as i can see.
    Last edited by Annonymous; 10-10-2011 at 11:06 PM.

  7. #7
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    client source code

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int main(int argc, char *argv[]) {
    int sockfd, portno; 
    char buffer[1026]; 
    struct hostent *server;
    struct sockaddr_in serv_addr, cli_addr;
    
    if(argc < 3) fprintf(stderr, "Ussage: %s IP Address port #", argv[0]);
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0) fprintf(stderr, "Error creating socket.");
    
    bzero((char *) &serv_addr, sizeof(serv_addr));
    server = gethostbyname(argv[1]);
    if(server == NULL) fprintf(stderr, "No such host.");
    portno = atoi(argv[2]);
    serv_addr.sin_family = AF_INET;
    memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
    serv_addr.sin_port = htons(portno);
    
    if(connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) fprintf(stderr, "Error connecting to server.");
    else {
    fprintf(stdout, "Made a connection to %s\n", inet_ntoa(cli_addr.sin_addr)); /*could this be a potential problem???*/
    }
    
    for( ; ; ) {
    fprintf(stdout, "Message: ");
    int i = sizeof(buffer)-1; if(i > 0) bzero(buffer, 1024);
    fgets(buffer, 1023, stdin);
    if(write(sockfd, buffer, sizeof(buffer)-1) < 0)
    fprintf(stderr, "Error writing to socket. WRITE()\n");
    
    i = sizeof(buffer)-1; if(i > 0) bzero(buffer, 1024);
    if(read(sockfd, buffer, sizeof(buffer)-1) < 0)
    {
    fprintf(stderr, "Error reading message from %s", inet_ntoa(cli_addr.sin_addr));
    }
    	else 
    	{
    	fprintf(stdout, "%s",buffer);
    	}
    
    }
    close(sockfd);
    }
    Last edited by Annonymous; 10-10-2011 at 11:07 PM.

  8. #8
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    i have tried everything to the best of my ability! I am coming up empty. So thanks for any and all help!

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    In your client, you declare buffer to be 1026 bytes, zero out 1024, fgets 1023 and transmit sizeof(buffer) - 1, which is 1025. On your server, you only read in 1024 bytes. That means that on the second read on the server, you are reading that 1 extra, non-zeroed byte leftover from the first send on the client.

    Other issues:
    • fgets will always null terminate, so no need to subtract 1 yourself, just do fgets(buffer, sizeof(buffer), stdin);
    • There's no need to transmit the whole buffer if the user only entered "foo". Use strlen(buffer) for the write length.
    • Make sure write writes all the bytes. You should do if (write(sockfd, buffer, strlen(buffer)) != buffer) to check for errors.
    • I'm not sure why you read from sockfd after writing to it. It doesn't seem to do anything.

    Here's some help with the client code. It's untested, but should get you going:
    Code:
    #define BUFFER_SIZE     1024
    int main(int argc, char *argv[])
    {
    ...
        int buffer_len, write_len;
        char *p, buffer[BUFFER_SIZE];
        for (;;) {
            printf("Message: ");
            fgets(buffer, sizeof(buffer), stdin);
            // trim the new line that fgets leaves in there
            p = strchr(buffer, '\n');
            if (p != NULL) {
                *p = '\0';
            }
            buffer_len = strlen(buffer);
            p = buffer;  // set p to the start of the buffer
            while (buffer_len > 0) {
                write_len = write(sockfd, p, buffer_len);
                if (write_len < 0) {
                    perror("write");  // produce a more useful error message that describes what went wrong
                    // exit if recovery is impossible -- check the docs for write() to see what values of errno you can't recover from
                }
                else {
                    // move p to the first unwritten character
                    p += write_len;
                    // adjust how many bytes we have left to send
                    buffer_len -= write_len;
                }
            }
        }
        close(sockfd);
        return 0;
    }
    Last edited by anduril462; 10-11-2011 at 10:05 AM.

  10. #10
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    anduril462, thanks for that client fix. But the problem is still there. So after i connect the client-server and the client prompts me for a message to send to the server, i send, it hangs....Then i close out the client with control c, and the server produces the exiting error handle that is provided if read is equal to zero. Which it shouldnt so i guess thats where it goes wrong. oddly, fter the connection is terminated, after the server prints exiting to the screen, it prints a blank message from the client too. But the client is already closed. SO read is being called twice. The first properly, then the second call is whats causing it to hang. Correct me if im wrong, please! What would cause that second call to read, with a blank message, after the connection has been terminated

    EDIT: I was reading up on the read call, and read() should legitamitly return 0.
    Last edited by Annonymous; 10-11-2011 at 12:31 PM.

  11. #11
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    ive been debugging some more and i i see that the handshake is good. The server sends the syn packet, the client sends its own syn packet and an ack. The server sends the ack and waits for input. The client sends a psh packet with the data, and the ack. Then the server sends an ack the acknowledge it recieved the data. The whole time read() maintains above 0 and never less than or equal to 0. But after that it sends fin packets, read is equal to 0. SO, now what from here? I guess ill go to McDonalds get some food. And keep at it. If someone wants to give me some help feel free. Thanks
    Last edited by Annonymous; 10-11-2011 at 01:47 PM.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I'm not totally clear on what you think the problem is and what you think should be happening. Generally, you don't need to be "debugging" at the TCP level. The sockets library handles everything for the TCP and IP layers. You only need to deal with the application layer.

  13. #13
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    ok anduril462, i set errno to every call. It is the same outcome for both the server and client. Lets say i fire up the server. It waits for the client to send data, with read. I send data to the server. they both hang. Now if i manually close the server fist, i get the errno message fro the client saying success, because read equals zero. Now i get the same exact message on the server if i manually close the client first. So How do i get around this? and return control back to the client??

  14. #14
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    solved the issue. Thanks for whoever responded/helped out

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ipc message-passing hangs
    By testguest in forum Linux Programming
    Replies: 7
    Last Post: 11-17-2010, 03:47 PM
  2. Select(); server help!
    By klipseracer in forum Networking/Device Communication
    Replies: 3
    Last Post: 03-02-2008, 11:16 PM
  3. Running two UDP server simultaneously using select()
    By PiJ in forum Networking/Device Communication
    Replies: 15
    Last Post: 01-31-2008, 10:49 AM
  4. Need winsock select() client & server source code or tutorial
    By draggy in forum Networking/Device Communication
    Replies: 2
    Last Post: 06-19-2006, 11:49 AM
  5. select() server
    By chrismiceli in forum Linux Programming
    Replies: 0
    Last Post: 09-09-2003, 08:56 PM