Thread: Socket communication hanging

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    34

    Socket communication hanging

    Socket problem

    Whenever i make a socket and use it for reading and writing, i have this problem,

    i open one socket on the server and it reads from it ( and of course the client writes to it) now the problem is if i add a write to the server and a read to the client

    the client hangs on the read while the server hangs on the first read which worked before, they both stop in the reads, i do not understand why the server dosnt move to the next write and stays at the read even after recieving data and hangs more and in that time the client reaches its read so they are both in a state of read and were stuck.

    EDIT: i did a netstat on the port i am using and i can see there is a socket left open in the TIME_WAIT status

    thank you in advance
    Last edited by zee; 08-04-2004 at 10:18 AM.

  2. #2
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    hmm let me try to ask this differently,

    how can i communicate between a server and client back and forth; with read and writes.

    Can someone give me an example?
    no need for all the connection stuff, just how the server would read from client then write to client and so on.

    thank you in advance

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Code:
    {
      int fd, got;
      char buf[256];
    
      // socket stuff to create connection goes here
    
      for(;;)
      {
        got = read(fd, buf, sizeof(buf));
        buf[got] = '\0';
        write(fd, "Your message was: ", strlen("Your message was: "));
        write(fd, buf, strlen(buf));
      }
    }
    Is that what you're asking for?

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Here's a simple little program I wrote. I just use 'telnet localhost 4445' to connect to it. It echos back whatever the client sends to it. It was just a really quick little stupid program so feel free to nitpick at it. I won't get offended

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define PORT 4445
    
    void sigchld_handler(int num)
    {
      while(waitpid(-1, NULL, WNOHANG) > 0);
    }
    
    void do_client(int des, int conn)
    {
      int got;
      char buf[4096];
    
      for(;;)
      {
        got = read(des, buf, SSIZE_MAX-1);
    
        if(got < 0)
        {
          perror("read()");
          close(des);
          exit(EXIT_FAILURE);
        }
        else if(got == 0)
        {
          printf("Connection %d disconnected\n", conn);
          close(des);
          exit(EXIT_SUCCESS);
        }
    
        buf[got] = '\0';
        printf("Received message from conn %d: %s", conn, buf);
        write(des, "Echo: ", strlen("Echo: "));
        write(des, buf, strlen(buf));
      }
    }
    
    int main(void)
    {
      struct sockaddr_in servaddr;
      int sock, des;
      int conn = 0;
      int opt = 1;
      int size = sizeof(struct sockaddr_in);
      pid_t child;
    
      signal(SIGCHLD, sigchld_handler);
    
      printf("Starting up on port %d\n", PORT);
    
      if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
      {
        perror("socket()");
        exit(EXIT_FAILURE);
      }
    
      if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
        sizeof(opt)) < 0)
      {
        perror("setsockopt()");
        exit(EXIT_FAILURE);
      }
    
      memset(&servaddr, 0, sizeof(servaddr));
      servaddr.sin_family = AF_INET;
      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
      servaddr.sin_port = htons(PORT);
    
      if(bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
      {
        perror("bind()");
        exit(EXIT_FAILURE);
    
      }
    
      if(listen(sock, 5))
      {
        perror("listen()");
        exit(EXIT_FAILURE);
      }
    
      puts("Accepting connections");
    
      for(;;)
      {
        if((des = accept(sock, (struct sockaddr *)&servaddr, &size)) < 0)
        {
          perror("accept()");
          exit(EXIT_FAILURE);
        }
    
        printf("New connection from %s!\n", inet_ntoa(servaddr.sin_addr));
        conn++;
    
        if(!(child = fork()))
          do_client(des, conn);
        else if(child == -1)
        {
          perror("fork()");
          exit(EXIT_FAILURE);
        }
        else  // Parent doesn't need it
          close(des);
      }
    
      return 0;
    }
    This is what I get when I run it and telnet into it from another shell:

    Shell 1:
    Starting up on port 4445
    Accepting connections
    New connection from 127.0.0.1!
    Received message from conn 1: I'm connection 1!
    Received message from conn 1: It works
    New connection from 127.0.0.1!
    Received message from conn 2: I'm connection 2!
    Received message from conn 2: I like C!
    Connection 2 disconnected
    Received message from conn 1: I just saw shell3 go away. But I'm still here!
    Received message from conn 1: bye
    Connection 1 disconnected
    Shell 2:
    $ telnet localhost 4445
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    I'm connection 1!
    Echo: I'm connection 1!
    It works
    Echo: It works
    I just saw shell3 go away. But I'm still here!
    Echo: I just saw shell3 go away. But I'm still here!
    bye
    Echo: bye
    ^]
    telnet> close
    Connection closed.
    Shell 3:
    $ telnet localhost 4445
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    I'm connection 2!
    Echo: I'm connection 2!
    I like C!
    Echo: I like C!
    ^]
    telnet> quit
    Connection closed.
    I hope that helps you a bit.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by zee
    hmm let me try to ask this differently,

    how can i communicate between a server and client back and forth; with read and writes.

    Can someone give me an example?
    no need for all the connection stuff, just how the server would read from client then write to client and so on.

    thank you in advance
    You could always consult Beej...

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    It is almost the same as mine yet mine hanged and yours dosnt ??

    well thank you quzah i fixed it by doing minor adjustments like urs. Thanks to itsme as well

    i have another wierd problem:

    I am trying to send an http 200 response back to the client
    Code:
    int http_ok(char *buffer, FILE *local_file, int socket, char *time){
    	printf("Sending ok\n");
    	write(socket,"HTTP/1.0 200 OK\r\nServer: home\r\nDate: ???\r\n",strlen("HTTP/1.0 200 OK\r\nServer: home\r\nDate: ???\r\n"));
    	char file[MAXDATASIZE];
    	
    	fread(file,1,MAXDATASIZE,local_file);
    	file[MAXDATASIZE] = '\0';
    	puts(file);
    	write(socket,file,strlen(file));
    	fflush(stdout);
    }
    here is what the output is from the terminal after a 2 tries, it vaires ...
    Code:
    host [~/a4]# ./forkclient localhost "GET ./forkserver.c HTTP/1.0"
    I have written to the socket.
    Recieved: HTTP/1.0 200 OK
    Server: CSC209S/2004
    Date: ???
    004
    host [~/a4]# ./forkclient localhost "GET ./forkserver.c HTTP/1.0"
    I have written to the socket.
    Recieved: HTTP/1.0 200 OK
    Server: CSC209S/2004
    Date: ???
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/
    What does 004 mean? if i try more it gives me the file i asked for but why does it output 004 on the first try SOMETIMES ?


    thanks in advance

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I'm not sure what's in local_file, but I'm assuming that's the problem. Why are you using fread() instead of fgets()? Does the message you want to write() for sure contain MAXDATASIZE bytes? If not then you'll need to capture the return value of fread() and null-terminate file accordingly.

  8. #8
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    A better way to read in a file and send it would be like this:
    Code:
    {
      char file[MAXDATASIZE];
    
      while(fgets(file, sizeof(file), local_file))
      {
        if(feof(local_file))
          break;
        printf("%s", file);
        write(socket, file, strlen(file));
      }
    }
    This is of course assuming it's always a text file you're sending.
    Last edited by itsme86; 08-05-2004 at 04:44 PM.

  9. #9
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    here is what the client is doing:

    Code:
    write(sockfd, argv[2], strlen(argv[2]));
    	printf("I have written to the socket.\r\n");
    	
    	read(sockfd,buf,MAXDATASIZE);
    	buf[MAXDATASIZE] = '\0';
    	printf("Recieved: %s\n",buf);
    and here is what the server is doing:

    Code:
    printf("path is: %s\n",filepath);
    		
    		FILE *local_file = fopen(filepath,"r");
    		
    		if( local_file != NULL){
    			http_ok(buffer, local_file, socket, time);
    		}	else{
    			http_bad(buffer, socket, time);
    		}
    and the http_ok function was pasted in my previous post

    the client adn server are restricted to sending and receiving MAXDATASIZE number of bytes.

    how could local_file be the problem?

    it is a file pointer that i got with fopen ( i derived the filepath through string operations )


    thank you very much

  10. #10
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I'm sorry, I didn't mean the problem was with the local_file variable itself, just what was in the file that local_file pointed to. Your http_ok() function assumes the file is always MAXDATASIZE bytes long which probably isn't the case.

    The fgets() method I wrote would be a better way to do it, but the client has to be able to read() in a loop as well. I believe a real HTTP server can tell the client how large the file is by having a string like "Size: 376" in the header. This could help your client figure out when it's gotten the whole file.

  11. #11
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    but if you look at the output of the server,

    Code:
    Client said: GET ./forkserver.c HTTP/1.0
    path is: ./forkserver.c
    Sending ok
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <sigCalling accept...
    the file is displayed properly ( done by the puts(file) ) but when i write that same string to the socket it is not received ?
    Code:
    st [~/a4]# ./forkclient localhost "GET ./forkserver.c HTTP/1.0"
    I have written to the socket.
    Recieved: OK 200
    here is my new http_ok method:

    Code:
    int http_ok(char *buffer, FILE *local_file, int socket, char *time){
    	printf("Sending ok\n");
    	char header[] = "OK 200";
    	int header_length = sizeof(header);
    	
    	write(socket,header,header_length);
    	
    	char file[MAXDATASIZE-header_length];
    	
    	fread(file,1,MAXDATASIZE-header_length,local_file);
    	file[MAXDATASIZE-header_length] = '\0';
    	printf("%s",file);
    	write(socket,file,sizeof(file));
    	fflush(stdout);
    }
    thank you for your ongoing help

  12. #12
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    So are you for sure always sending MAXDATASIZE bytes? I mean, is the file you're sending always that length? If not, then that's your problem. You need to write() exactly the same number of bytes as is the length of the file you're sending. You can get this information from the return value of fread().

    And when your client read()s the data from the socket, read() returns the number of bytes received and that's where you should be null-terminating the read buffer (i.e. bytes_received = read(sockfd, buf, MAXDATASIZE); buf[bytes_received] = '\0'; )
    Last edited by itsme86; 08-05-2004 at 05:19 PM.

  13. #13
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    What about this?

    Code:
    int http_ok(char *buffer, FILE *local_file, int socket, char *time){
    	printf("Sending ok\n");
    	char header[] = "OK 200";
    	int header_length = sizeof(header);
    	
    	write(socket,header,header_length);
    	
    	int bytes_read;
    	char file[MAXDATASIZE-header_length];
    	if((bytes_read = fread(file,1,MAXDATASIZE-header_length,local_file)) < 0)
    	{
    		perror("fread()");
    		close(socket);
    		exit(1);
    	}
    	/* if 0 bytes were read then the client isnt talking anymore */
    	else if(bytes_read == 0)
    	{
    		printf("Empty.\n");
    		close(socket);
    		exit(1);
    	}
    	
    	file[bytes_read] = '\0';
    	printf("%s",file);
    	write(socket,file,sizeof(file));
    	fflush(stdout);
    }
    OUTPUT:

    Server said:
    Code:
    Starting up on port 11000
    Calling accept...
    Client said: GET ./forkserver.c HTTP/1.0
    path is: ./forkserver.c
    Sending ok
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <sigCalling accept...
    Client shell:

    Code:
    thost [~/a4]# ./forkclient localhost "GET ./forkserver.c HTTP/1.0"
    I have written to the socket.
    Recieved: OK 200
    admin@esmarthost [~/a4]#
    it still did not print the file to the clients screen like i made in the method:

    Code:
    write(sockfd, argv[2], strlen(argv[2]));
    	printf("I have written to the socket.\r\n");
    	
    	numbytes = read(sockfd,buf,MAXDATASIZE);
    	buf[numbytes] = '\0';
    	printf("Recieved: %s\n",buf);


    tahnk you

  14. #14
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    heh dummmie me,

    i got the output fixed, i did another read since i did 2 writes
    and now the file is also printed

    client does this now:
    Code:
    	write(sockfd, argv[2], strlen(argv[2]));
    	printf("I have written to the socket.\r\n");
    	
    	numbytes = read(sockfd,buf,MAXDATASIZE);
    	buf[numbytes] = '\0';
    	printf("Recieved response: %s\n",buf);
    	
    	numbytes = read(sockfd,buf,MAXDATASIZE);
    	buf[numbytes] = '\0';
    	printf("file: %s\n",buf);
    and i think i got the strings properly terminated
    what do u think itsme?

    thank you again

  15. #15
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    It looks right. Now you just need to add some error handling If the client disconnected read() will return 0

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. socket programming question, closing sockets...
    By ursula in forum Networking/Device Communication
    Replies: 2
    Last Post: 05-31-2009, 05:17 PM
  2. when to close a socket
    By Wisefool in forum Networking/Device Communication
    Replies: 5
    Last Post: 11-02-2003, 10:33 AM
  3. problem closing socket
    By Wisefool in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-29-2003, 12:19 PM
  4. problem closing a socket
    By Wisefool in forum C Programming
    Replies: 1
    Last Post: 10-28-2003, 01:38 PM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM