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