Thread: Read and write hanging

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

    Read and write hanging

    Helo ladies and gentleman,

    I have this wierd problem i can not figure out,

    i have a server and a client proggies, they both work fine on the connection part. The problem is:

    when i write to the socket from the client there is read in the server so it reads it, but then the server writes to a log file and that is where it stops.

    Code:
    switch(fork()){
    			case 0:
    				/* child doesn't need the listener */
    				printf("Process %d; I am going to service the client.\n", getpid());
    				/* close listening socket since i am not listening */
    				close(sockfd); 
    				
    				/* input string from client */
    				char buf[MAXDATASIZE];
    				
    				printf("I am going to read from the client now.\n");
    				/* read max bytes and set numbytes to the amount read */
    				int numbytes = Readn(new_fd, buf, MAXDATASIZE);
    				/* null terminate the string */
    				buf[numbytes] = '\0';
    				
    				printf("Client said: %s", buf);
    				close(new_fd);
    				FILE *log_file_in = fopen("./log.txt","a");
    				printf("Writing to file now:\n");
    				fwrite(&buf[0],numbytes,255,log_file_in);
    				fclose(log_file_in);
    				
    				printf("Process %d; my job is done.\n", getpid());
    				exit(0);
    				break;
    			case -1:
    				perror("fork error");
    				break;
    			default:
    				/* only parent gets here */
    				/* parent doesn't need this */
    				close(new_fd);
    		}
    if you saw above there is a printf line that says "Writing to file now:" the server outputs that and stops i can only quit by pressing ctrl-c.

    i dont understand why it dosnt execute the fwrite ??


    please help
    thank you in advance

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I don't think you're using fwrite() correctly. You're trying to write numbytes*255 total bytes to the file.
    You might want to just try: fprintf(log_file_in, "%s\n", buf);

    EDIT: Or you can use fwrite(buf, 1, numbytes, log_file_in); but you'll be missing a \n if there isn't one stored at buf[numbytes-1] so all of your log messages will run together on the same line.
    Last edited by itsme86; 08-03-2004 at 08:33 PM.

  3. #3
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    i tried that it still the same problem,

    here is what the client program sends:

    Code:
    	Writen(sockfd, "Sup?\n", 5);
    	printf("I have written to the socket.\n");
    	
    	/* close the socket */
                    close(sockfd);
    note: Writen is just a wrapped version of write() and Readn is a wrapped version of read()

    this is the output i get:

    Code:
    Calling accept...
    completed accept
    server: got connection from 127.0.0.1
    Calling accept...
    Process 9389; I am going to service the client.
    I am going to read from the client now.
    Client said: Sup?
    Writing to file now:
    the process does not reach the line :
    printf("Process %d; my job is done.\n", getpid());
    and does not exit.

    if i get rid of the second write in the code shown in the previous post then it exits fine. Whenever i put 2 read or writes consecutively i get this problem.

    thank you

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Have you tried running your server with strace? If your program is called myserver then just type: strace myserver

    That should at least show you where it's hanging. If you post the whole program I'll compile it and see what I come up with if you want.

    EDIT: The only thing I can really think of right now is that the fopen() call is failing. you might want to add a test if(log_file_in == NULL) puts("Couldn't open log file!"); or something to that effect after your fopen() call.
    Last edited by itsme86; 08-03-2004 at 08:41 PM.

  5. #5
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    I tried to check if fopen returned a value < 0 but it does not. nad it sitll hangs in the same spot, strace gives me :

    Code:
    ... , Writing to file now:
    0xbfffdfc0, [16])             = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) ---
    wait4(-1, NULL, 0, NULL)                = 11491
    sigreturn()                             = ? (mask now [])
    accept(3,
    here is my server code:

    Code:
    /*
    ** server.c -- a stream socket server demo
    */
    
    #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 <signal.h>
    #include <unistd.h>
    #include "readline.c"
    #include "readn.c"
    #include "writen.c"
    
    /* define port if needed */
    #ifndef PORT
    #define PORT 11000
    #endif
    
     /* max number of bytes we can get at once  */
    #define MAXDATASIZE (255)
    
    /* how many pending connections queue will hold*/
    #define BACKLOG (5)
    
    void sigchld_handler(int s){
        wait(NULL);
    }
    
    int main(void){
    	/* listen on sock_fd, new connection on new_fd*/
        int sockfd, new_fd;
    	/* my address information */
        struct sockaddr_in my_addr;
    	/* connector's address information */
        struct sockaddr_in their_addr;
    	/* size of accept socket */
        int sin_size;
    	/* used for child signaling */
        struct sigaction sa;
    
    	FILE *log_file_in;
    	int numbytes;
    	
    	/* input string from client */
    	char buf[MAXDATASIZE];
    	
    	/* create the socket at sockfd, otherwise output error */
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }
    
    	/* Make the socket reusable */
    	/* note: i had a problem that when i closed my server it would not let me start it
    		again right after because bind error: address already in use. So i did some 
    		searching and learned about setsocketopt and the SO_REUSEADDR property
    		to solve the problem. */
    	int opt = 1;
    	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
      
    	 /* host byte order */
        my_addr.sin_family = AF_INET;        
    	/* short, network byte order */
        my_addr.sin_port = htons(PORT);     
    	/* automatically fill with my IP */
        my_addr.sin_addr.s_addr = INADDR_ANY; 
    	/* zero the rest of the struct */
        bzero(&(my_addr.sin_zero), 8);        
    
    	/* bind name: sockfd to my address, otherwise output error */
        if (bind(sockfd, (struct sockaddr *)&my_addr, 
    	     sizeof(struct sockaddr)) == -1) {
            perror("bind");
            exit(1);
        }
    
    	/* listen on sockfd with a backlog, otherwise output error */
        if (listen(sockfd, BACKLOG) == -1) {
            perror("listen");
            exit(1);
        }
    
    	/* ?? */
        sa.sa_handler = sigchld_handler; /* reap all dead processes */
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        if (sigaction(SIGCHLD, &sa, NULL) == -1) {
            perror("sigaction");
            exit(1);
        }
    	/* ?? */
    
    	/* main accept() loop*/
        while(1) {  
    		
    		/* accept incoming connections, otherwise output error */
            sin_size = sizeof(struct sockaddr_in);
    		printf("Calling accept...\n");
            if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, 
    			     &sin_size)) == -1) { 
                perror("accept");
    			/* if an error occured then restart loop for new connection */
                continue;
            }
    		printf("completed accept\n");
    		
    		/* ?? */
            printf("server: got connection from %s\n",
    	    inet_ntoa(their_addr.sin_addr));
    		/* ?? */
    		
    		switch(fork()){
    			case 0:
    				/* child doesn't need the listener */
    				printf("Process %d; I am going to service the client.\n", getpid());
    				/* close listening socket since i am not listening */
    				close(sockfd); 
    				
    				printf("I am going to read from the client now.\n");
    				/* read max bytes and set numbytes to the amount read */
    				numbytes = Readn(new_fd, buf, MAXDATASIZE);
    				/* null terminate the string */
    				buf[numbytes] = '\0';
    				
    				printf("Client said: %s", buf);
    				close(new_fd);
    				log_file_in = fopen("./log.txt","a");
    				if(log_file_in < 0){
    					perror("fopen");
    				}
    				printf("Writing to file now:\n");
    				fwrite(buf, 1, numbytes, log_file_in);
    				fclose(log_file_in);
    				
    				printf("Process %d; my job is done.\n", getpid());
    				exit(0);
    				break;
    			case -1:
    				perror("fork error");
    				break;
    			default:
    				/* only parent gets here */
    				/* parent doesn't need this */
    				close(new_fd);
    		}
        }
    
        return 0;
    }
    here is client code

    Code:
    /*
    ** client.c -- a stream socket client demo
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <strings.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include "readn.c"
    #include "writen.c"
    
    /* the port client will be connecting to  */
    #define PORT (11000)
     /* max number of bytes we can get at once  */
    #define MAXDATASIZE (255)
    
    int main(int argc, char *argv[]) {
    	/* socket for connection */
        int sockfd;
    	/* used to determine amount of bytes read */
    	int numbytes;
        char buf[MAXDATASIZE];
        struct hostent *he;
    	/* connector's address information  */
        struct sockaddr_in their_addr;
    
    	/* If there are not enough arguments output to stderr and halt */
        if (argc != 2) {
            fprintf(stderr,"usage: client hostname\n");
            exit(1);
        }
    
    	/* get the host info, otherwise error */
        if ((he=gethostbyname(argv[1])) == NULL) {  
            perror("gethostbyname");
            exit(1);
        }
    
    	/* create the socket, otherwise error */
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }
    
    	/* host byte order */
        their_addr.sin_family = AF_INET;    
    	/* short, network byte order */
        their_addr.sin_port = htons(PORT);
    	/* ?? */
        their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    	/* ?? */
    	 /* zero the rest of the struct */
        bzero(&(their_addr.sin_zero), 8);  
    
    	/* connect the socket, otherwise error */
        if (connect(sockfd, (struct sockaddr *)&their_addr, 
    		sizeof(struct sockaddr)) == -1) {
            perror("connect");
            exit(1);
        }
    
    	Writen(sockfd, "Sup?\n", 5);
    	printf("I have written to the socket.\n");
    	
    	/* close the socket */
        close(sockfd);
    
        return 0;
    }
    and here is the wrapper functions Readn and Writen

    Readn

    Code:
    /* include readn */
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    
    ssize_t		/* Read "n" bytes from a descriptor. */
    readn(int fd, void *vptr, size_t n)
    {
        size_t	nleft;
        ssize_t	nread;
        char	*ptr;
        
        ptr = vptr;
        nleft = n;
        while (nleft > 0) {
    	if ( (nread = read(fd, ptr, nleft)) < 0) {
    	    if (errno == EINTR)
    		nread = 0;		/* and call read() again */
    	    else
    		return(-1);
    	} else if (nread == 0)
    	    break;				/* EOF */
    	
    	nleft -= nread;
    	ptr   += nread;
        }
        return(n - nleft);		/* return >= 0 */
    }
    
    
    ssize_t
    Readn(int fd, void *ptr, size_t nbytes)
    {
        ssize_t n;
        
        if ( (n = readn(fd, ptr, nbytes)) < 0)
    	perror("readn error");
        return(n);
    }
    Writen

    Code:
    /* include writen */
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    
    /* Write "n" bytes to a descriptor. */
    ssize_t writen(int fd, const void *vptr, size_t n)
    {
        size_t		nleft;
        ssize_t		nwritten;
        const char	*ptr;
    
        ptr = vptr;
        nleft = n;
    	/* keep writing until no more left to write */
        while (nleft > 0) {
    		/* if i did not write anythign then chk if i got a interrupt signal and
    			so then retry write on the same byte ( do not increment pointer ) */
    		if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
    			if (errno == EINTR)
    			/* and call write() again without moving to the next byte */
    			nwritten = 0;		
    			else
    			/* another error occured */
    			return(-1);		
    		}
    	
    	/* decrease the number of written and move to next byte */
    	nleft -= nwritten;
    	ptr   += nwritten;
        }
    	
    	/* return the number of writes */
        return(n);
    }
    
    /* Error checked version of writen above */
    void Writen(int fd, void *ptr, size_t nbytes)
    {
        if (writen(fd, ptr, nbytes) != nbytes)
    	perror("writen error");
    }

    thank you again

  6. #6
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Well, right away I have a new theory that it has to do with reaping the child processes. I bet if you added an fflush(stdout); write before the exit(); call that it would show up correctly.

    I'll actually compile the code and see if I can find anything else.

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    It actually seems to work fine on my system once I moved int opt = 1; up to the rest of the variable definitions.
    $ ./server
    Calling accept...
    completed accept
    server: got connection from 127.0.0.1
    Calling accept...
    Process 10624; I am going to service the client.
    I am going to read from the client now.
    Client said: Sup?
    Writing to file now:
    Process 10624; my job is done.
    (stops here. Waits for another connection)
    completed accept
    server: got connection from 127.0.0.1
    Calling accept...
    Process 10626; I am going to service the client.
    I am going to read from the client now.
    Client said: Sup?
    Writing to file now:
    Process 10626; my job is done.
    That's the result from me running the client twice. The italicized line in parentheses I added in myself of course.

  8. #8
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    wierd still does not work for me, i moved the declaration up and also added teh fflush still same problem

  9. #9
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    oh nevermind, its working now,

    thankkkkkkkkkkkkkkkkkkk you itsme!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 04-17-2009, 04:41 PM
  2. Problems with fstream, one variabile for write and read
    By Smjert in forum C++ Programming
    Replies: 3
    Last Post: 02-03-2009, 10:19 PM
  3. read write lock in C#
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 04-16-2008, 08:49 AM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM