Thread: Help: uncomprehendable problem

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

    Help: uncomprehendable problem

    Hello ladies and gents,

    I have these two files, server and client codes, they run fine but i just can not get the server to properly send file contents to the client. I am just sending a string of x bytes to the client but it does not read it properly. I have tried everything i just can not get it to work.

    please compile these two files and run em

    server:
    Code:
    gcc forkserver.c -o forkserver
    ./forkserver
    client:
    Code:
    gcc forkclient.c -o forkclient
    ./forkclient localhost "GET ./myfile HTTP/1.0"
    or
    Code:
    gcc forkclient.c -o forkclient
    ./forkclient localhost "hello"
    you can send a get request to the server and recieve a HTTP response or just send a message to the server. The latter works properly so i think the problem is in the http sending stuff.

    here are the two files:

    forkserver.c:
    Code:
    #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 <time.h>
    
    /* 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)
    /* fail */
    #define FAIL (-1)
    /* success */
    #define SUCCESS (0)
    /* TRUE */
    #define TRUE (1)
    
    /* determines if an http response needs to be taken */
    int handle_http(char *buffer, int socket);
    /* inserts data into the log file */
    int log_data(const char *buffer,const int numbytes,const char *ip);
    /* sends an HTTP OK 200 response */
    int http_ok(FILE *local_file, int socket, char *time);
    /* sends an HTTP BAD REQUEST 400 response */
    int http_bad(int socket, char *time);
    /* child handler */
    void sigchld_handler(int s){
        wait(NULL);
    }
    
    /* main program */
    int main(void){
    	/* used to make socket persistent to prevent TIME_WAIT status */
    	int opt = 1;
    	/* listen on sock_fd, new connection on new_fd*/
        int sockfd, new_fd;
    	/* size of accept socket */
        int sin_size;
    	/* number of bytes read during read */
    	int numbytes;
    	/* input string from client */
    	char buf[MAXDATASIZE];
    	/* my address information */
        struct sockaddr_in my_addr;
    	/* connector's address information */
        struct sockaddr_in their_addr;
    	/* used for child signaling */
        struct sigaction sa;
    	
    	//printf("Starting up on port %d\n", PORT);
    	
    	/* create the socket at sockfd, otherwise output error */
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <= FAIL) {
            perror("FAIL on socket, error:");
            exit(FAIL);
        }
    
    	/* make the sockets reusable and error if they fail */
    	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
    			sizeof(opt)) <= FAIL){
    		perror("FAIL on setsockopt, error:");
    		exit(FAIL);
    	}
      
    	/* zero the struct */
    	memset(&my_addr, 0, sizeof(my_addr));
    	/* 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; 
    
    	/* bind name: sockfd to my address, otherwise output error */
        if (bind(sockfd, (struct sockaddr *)&my_addr, 
    			sizeof(struct sockaddr)) <= FAIL) {
            perror("FAIL on bind, error:");
            exit(FAIL);
        }
    
    	/* listen on sockfd with a backlog, otherwise output error */
        if (listen(sockfd, BACKLOG) <= FAIL) {
            perror("FAIL on listen, error:");
            exit(FAIL);
        }
    
    	/* ?? */
        sa.sa_handler = sigchld_handler; /* reap all dead processes */
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        if (sigaction(SIGCHLD, &sa, NULL) <= FAIL) {
            perror("FAIL on sigaction, error:");
            exit(FAIL);
        }
    	/* ?? */
    
    	/* main accept() loop*/
        while(TRUE) {  
    		/* 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)) <= FAIL) { 
                perror("FAIL on accept, error:");
    			close(new_fd);
    			/* 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 that forks out new child process for each client */
    		switch(fork()){
    			case 0: /* child goes here */
    				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 */
    				if((numbytes = read(new_fd, buf, MAXDATASIZE)) <= FAIL){
    					perror("read()");
    					close(new_fd);
    					exit(FAIL);
    				}
    				/* if 0 bytes were read then the client isnt talking anymore */
    				else if(numbytes == 0){
    					printf("Connection disconnected: nothing to read. \n");
    					close(new_fd);
    					exit(SUCCESS);
    				}
    				
    				/* null terminate the string */
    				buf[numbytes] = '\0';
    				/* close the socket no need for it anymore */
    				printf("Client said: %s\n", buf);
    				//close(new_fd);
    				
    				/* check if the string is http and send proper response otherwise ignore */
    				printf("http?: %i\n",handle_http(buf, new_fd));
    				
    				/* write log of current connection to the file */
    				//log_data(buf,numbytes,inet_ntoa(their_addr.sin_addr));
    				
    				/* exit */
    				printf("Process %d; my job is done.\n", getpid());
    				fflush(stdout);
    				close(new_fd);
    				exit(SUCCESS);
    				break;
    			case FAIL:
    				/* error occured with fork() */
    				perror("FAIL on fork, error:");
    				break;
    			default:
    				/* only parent gets here */
    				/* parent doesn't need this */
    				close(new_fd);
    		}
        }
    
        return SUCCESS;
    } /* end main */
    
    /* determines if an http response needs to be taken */
    int handle_http(char *buffer, int socket){
    	/* the substring that starts with GET */
    	char *subst;
    	/* the substring that starts with HTTP/1. */
    	char *subhttp;
    	/* current time vars */
    	time_t timer = time(NULL);
    	/* formatted time */
    	char *time = ctime(&timer);
    	printf("The time is: %s",time);
    	
    	/* if GET is at the start of hte line then consider http request */
    	if((subst = strstr(buffer,"GET ")) != NULL && (buffer - subst) == 0){
    		/* should it be a line terminated with CR LF? */
    		/* find the end of the GET request, it is the protocol name */
    		// check this
    		
    		/* if the line does not ends with valid HTTP fail */
    		if((subhttp = strstr(buffer," HTTP/1.0")) == NULL){
    			return FAIL;
    		}
    		
    		printf("subst: %s, subhttp: %s, with length: %i\n",subst,subhttp,(buffer-subhttp));
    		
    		/* The file path is (subhttp-buffer)-4 characters long plus 1 for null char */
    		char filepath[(subhttp-buffer)-4+1];
    		/* copy the path portion of the GET request to filepath */
    		strncpy(filepath, subst+4, (subhttp-buffer)-4);
    		/* null terminate the string */
    		filepath[(subhttp-buffer)-4] = '\0';
    		printf("path is: %s\n",filepath);
    		
    		/* open the requested file */
    		FILE *local_file = fopen(filepath,"r");
    		
    		/* if it coudlnt be opened then return the appropriate response */
    		if( local_file != NULL){
    			/* OK 200 */
    			http_ok(local_file, socket, time);
    		}	else{
    			/* BAD REQUEST 400 */
    			http_bad(socket, time);
    		}
    		
    		return SUCCESS;
    	}
    	printf("This is not a http request");
    	write(socket,"stop\0",strlen("stop\0"));
    	/* return fail since it was not an http request */
    	return FAIL;
    }
    
    /* sends an HTTP BAD REQUEST 400 response */
    int http_bad(int socket, char *time){
    	printf("Sending bad\n");
    	write(socket,"BAD 400\0",8);
    	fflush(stdout);
    }
    
    /* sends an HTTP OK 200 response */
    int http_ok(FILE *local_file, int socket, char *time){
    	printf("Sending ok\n");
    	/* header string */
    	char header[] = "OK 200\0";
    	/* header size */
    	int header_size = sizeof(header);
    	/* bytes read from file */
    	int bytes_read;
    	/* local file data */
    	char file[MAXDATASIZE-header_size];
    	
    	/* write the HTTP header to the socket */
    	write(socket,header,header_size);
    	/* read from local file */
    	if((bytes_read = fread(file,1,MAXDATASIZE-header_size,
    			local_file)) <= FAIL){
    		perror("FAIL on fread, error:");
    		close(socket);
    		exit(FAIL);
    	}
    	
    	printf("bytes_read: %i\n and file: %s\n", bytes_read,file);
    	
    	/* null terminate the file string */
    	file[bytes_read] = '\0';
    	printf("%s",file);
    	/* write file data to the socket */
    	write(socket,file,sizeof(file));
    	fflush(stdout);
    }
    
    /* inserts data into the log file */
    int log_data(const char *buffer,const int numbytes,const char *ip){
    	/* log file pointer */
    	FILE *log_file_in;
    	
    	/* open the log file for append */
    	if((log_file_in = fopen("./log.txt","a")) == NULL){
    		perror("FAIL on fopen, error:");
    		exit(FAIL);
    	}
    	
    	//printf("Logging data...");
    	/* write log entry */
    	fprintf(log_file_in,"Client: got connection from %s\n", ip);
    	fprintf(log_file_in,"Client message log:\n\n");
    	fwrite(buffer, 1, numbytes, log_file_in);
    	fprintf(log_file_in,"\n\nEND of client message log.\n\n");
    	fclose(log_file_in);
    	//printf(" appended!\n");
    }
    forkclient.c:
    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[]) {
    	int opt = 1;
    	/* 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 < 3) {
            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);
        }
    
    	  if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
        sizeof(opt)) < 0)
      {
        perror("setsockopt()");
        exit(EXIT_FAILURE);
      }
    	
    	/* zero the memory */
    	memset(&their_addr, 0, sizeof(their_addr));
    	/* 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);
        }
    
    	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("numbytes: %i\n and buf: %s\n", numbytes,buf);
    	if(strncmp("stop",buf,numbytes) != 0){
    		printf("Recieved response: %s\n",buf);
    		
    		numbytes = read(sockfd,buf,MAXDATASIZE);
    		buf[numbytes] = '\0';
    		printf("file: %s\n",buf);
    	} else{
    		printf("No response\n");
    	}
    	/* close the socket */
        close(sockfd);
    
        return 0;
    }
    
    int log_data(const char *buffer,const int numbytes,const char *ip){
    	/* log file pointer */
    	FILE *log_file_in;
    	
    	/* open the log file for append */
    	if((log_file_in = fopen("./log.txt","a")) < 0){
    		perror("fopen");
    		exit(1);
    	}
    	
    	printf("Logging data...");
    	fprintf(log_file_in,"Client: got connection from %s\n", ip);
    	fprintf(log_file_in,"Client message log:\n\n");
    	fwrite(buffer, 1, numbytes, log_file_in);
    	fprintf(log_file_in,"\n\nEND of client message log.\n\n");
    	fclose(log_file_in);
    	printf(" appended!\n");
    }
    please help as soon as you can am at my limit lo, i just can not figure it out. I checked string terminations, sending and receiving i dont know what could give me the problem i get. Try a run at it and see the problem.


    thank you very much

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I haven't come anywhere near looking at all the code, but I picked this out right away from your http_ok() function in forkserver.c
    Code:
    write(socket,file,sizeof(file));
    You don't want to write sizeof(file) bytes (the size of the buffer). You want to write the number of bytes that corresponds to the length of the file (bytes_read).

    EDIT: P.S. You define MAXDATASIZE as 255 and then you can only read MAXDATASIZE minus the header size bytes? You better only be planning on sending small files. Otherwise, you have no functionality right now of telling the client that the requested file is too large to send. The server will quitely send the first couple hundred bytes of the file and the client has no way of knowing that it's incomplete.
    Last edited by itsme86; 08-10-2004 at 10:58 AM.
    If you understand what you're doing, you're not learning anything.

  3. #3
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Try implementing some functions to handle the reading and writing for you. Here are some examples of differing read functions:
    http://cboard.cprogramming.com/showt...333#post321434
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  4. #4
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    but did u see the output i get from the programs i posted? can u explain that?

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    No I didn't because you don't stick to coding standards and therefore it won't compile on my compiler. Remember that all variable definitions have to come at the beginning of a code block.

    I also find your code very difficult to read with the over-abundance of comments:
    /* header size */
    int header_size = sizeof(header);
    I mean come on, really.
    If you understand what you're doing, you're not learning anything.

  6. #6
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Also, why are you adding your own null-terminators to string literals? The compiler takes care of that for you. You don't need to do thinks like char header[] = "OK 200\0";. char header[] = "OK 200"; is fine.
    If you understand what you're doing, you're not learning anything.

  7. #7
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    For me, the server sends a partial file, which the client receives OK. The reason it's only partial , is because this line restricts the number of bytes read from the source file:
    Code:
    if((bytes_read = fread(file,1,MAXDATASIZE-header_size,
     			local_file)) <= FAIL)
    If you think this is not the same symptoms as you're seeing, maybe post a more descriptive message about what your problem really is.

    Also, you need to understand that one call to read() isn't necessarily going to get you all the data the other end is send()ing. TCP/IP is a stream protocol, the data being sent between the client and server can be split into chunks by any component that it traverses through. If you look at those read functions I pointed you to earlier, you'll see that they call recv() multiple times, until they're finished doing what you want them to. This type of coding is key to handling data transmission correctly.

    Remember to check the return from every send and receive call to ensure they did what you asked, don't assume they worked:
    Code:
     write(sockfd, argv[2], strlen(argv[2]));
     printf("I have written to the socket.\r\n");
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  8. #8
    Registered User
    Join Date
    Jun 2004
    Posts
    34
    yeah itsme i am trying to learn the standards, lol this is my first time doing C . I will try out hte suggestion asap and get back to you guys, thanks for the ongoing help.

    oh and about the read and write wrapper functions, i had em earlier but they seemed useless thats why i got rid of them. Will add em back thanks for the tip Hammer.



    thank you very much guys/girls expect a post soon!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM