i am trying to write a simple webserver which serves 1 htnl file but i dont know where i am going wrong i am not able to read the file any suggestions ?

listen(sockfd,5);
		clilen = sizeof(cli_addr);
		newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
		
		if(newsockfd < 0) error("eror on accept");
		bzero(buffer,256);
		FILE* open;
		open =fopen("/home/rocco/www/home.hml","r"); 
		n = recv(newsockfd,open,255,0);
		
		if(n< 0) error("error reading from socket");
		printf("here is the message: %s\n", buffer);
		n = send(newsockfd,open, 18,0);
		if(n<0) error("writing to socket");
		close(newsockfd);
		close(sockfd);
		return 0;

Recommended Answers

All 29 Replies

recv 's second argument is a buffer, not a FILE* . You likely need something like:

FILE * fout = fopen (...);
unsigned char * buff[255] = {0};
n = recv (newsockfd, buff, 255, 0);
// ...
fprintf (fout, "%s", buff);
// ...

Here's a simple server which receives a filename from a client, opens the file and writes the data to the client. If the file can't be found, it writes an error message to the client. From this bare shell, you should be able to create your simple web server.

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#define DEFAULT_PROTOCOL 0
#define PORT 50000
#define MAXLINE 4096
#define PATH_SIZE 128

int main(int argc, char**argv)
{
  int listenfd, connfd, val = 1;
  char recvline[MAXLINE];
  struct sockaddr_in servaddr;
  
  signal(SIGCHLD, SIG_IGN);
  
  if ((listenfd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL)) < 0)
  {
	perror("socket");
	exit(EXIT_FAILURE);
  }
  
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
  
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(PORT);
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  
  if ((bind(listenfd, (const struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
  {
	perror("bind");
	exit(EXIT_FAILURE);
  }
  
  if ((listen(listenfd, 5)) < 0)
  {
	perror("listen");
	exit(EXIT_FAILURE);
  }
  
  for (;;)
  {
	connfd = accept(listenfd, NULL, NULL);
	
	if (fork())
	{
	  close(connfd);
	}
	else
	{
	  int n = 0, i = 0;
	  char filename[PATH_SIZE];
	  FILE *fd = NULL;
	  char err_msg[] = "Could not open ";
	  char newline[] = "\n";
	  
	  close(listenfd);
	  
	  while ((n = read(connfd, &filename[i], (PATH_SIZE - i))) > 0)
	  {
		i += n;
	  }
	  filename[i] = '\0';
	  
	  if (!(fd = fopen(filename, "r")))
	  {
		write(connfd, err_msg, strlen(err_msg));
		write(connfd, filename, strlen(filename));
		write(connfd, newline, strlen(newline));
		exit(EXIT_FAILURE);
	  }
	  
	  while ((write(connfd, recvline, fread(recvline, sizeof(char), MAXLINE, fd))))
	  {}
	  
	  fclose(fd);
	  close(connfd);
	  exit(EXIT_SUCCESS);
	}
  }
  return EXIT_SUCCESS;
}

can you please explain the while loop

while ((write(connfd, recvline, fread(recvline, sizeof(char), MAXLINE, fd))))
	  {}

This is a loop that first fread's into the buffer recvline and then writes the buffer(recvline) to the client connfd.

is maxline, max number of bytes written ?

plus i need to change the reciveline line to the filename as i want the file to be read ?

this is how i got so far still cant send my file

listen(listenfd,10);
		 client_length = sizeof(clientaddr);
 	
		 connectfd = accept(listenfd, (struct sockaddr *)&clientaddr, &client_length);
		 if (connectfd < 0)
  	 		error("eRROR on accept");
			 bzero(buffer,256);
		
	
			
		  n = read(connectfd, buffer, 255 );
	 	  if (n < 0) error("ERROR reading from socket");
	 	  FILE *open = NULL;
	 	  char err_msg[] = "Could not open";
	 	  
	 	  
	 	  
		
	if(!(open = fopen("/home/user/www/home.html", "r")))
	
	{
		n = write(connectfd, err_msg, strlen(err_msg));
		n = write(connectfd, "/home/user/www/home.html", strlen("/home/user/www/home.html"));
		n = recv(connectfd, buff, 255, 0);
	
	
		exit(EXIT_FAILURE);
		
		}
		
		while ((write(connectfd, recive, fread(recive, sizeof(char), MAXBYTE, open))))
		{}
		
		fclose(open);
		close(connectfd);
		exit(EXIT_SUCCESS);
		}

Line 19, your if statement is incorrect, you want the code executed if fopen succeeds. The way you have it now, the code is executed when fopen fails.

i have changed to execute when fopen succeeds, now i get a segmentation fault, i do not know what memory im accessing which im not supposed to ??

i know that this line is causing the segmentation fault

if(open = fopen("/home/user/www/home.html", "rb"))

could it be the privileges set on the file ?

i know that this line is causing the segmentation fault

if(open = fopen("/home/user/www/home.html", "rb"))

could it be the privileges set on the file ?

First, does the file exist? If it exists, can you open it? Try opening the file with an editor. Finally, what system are you running this code on?

i running this code on ubuntu 10.10 the file does exist and i defiantly can open it with a file editor

OK, here's a simple client/server example that requests a file.

client.c

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define DEFAULT_PROTOCOL 0
#define PORT 50000
#define MAXLINE 4096

int main(int argc, char**argv)
{
  int clientfd, tot = 0, n = 0;
  char recvline[MAXLINE];
  struct sockaddr_in servaddr;
  
  if ( argc != 3 )
  {
	fputs("usage error - a.out <IPaddress> <Filename>\n", stderr);
	exit(EXIT_FAILURE);
  }
  
  if ((clientfd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL)) < 0)
  {
	perror("socket");
	exit(EXIT_FAILURE);
  }
  
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(PORT);
  
  if ((inet_pton(AF_INET, argv[1], &servaddr.sin_addr.s_addr)) <= 0)
  {
	fputs("conversion error!\n", stderr);
	exit(EXIT_FAILURE);
  }
  
  if ((connect(clientfd, (const struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
  {
	perror("connect");
	exit(EXIT_FAILURE);
  }
  
  write(clientfd, argv[2], strlen(argv[2]));
  
  shutdown(clientfd, SHUT_WR);
  
  while ((n = read(clientfd, recvline, MAXLINE)) > 0)
  {
	recvline[n] = '\0';
	tot += n;
	fputs(recvline, stdout);
  }
  if ( n < 0 )
	fputs("read error!\n", stderr);
  fprintf(stdout, "client read %d bytes!\n", tot);
  close(clientfd);
  exit(EXIT_SUCCESS);
}

server.c

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#define DEFAULT_PROTOCOL 0
#define PORT 50000
#define MAXLINE 4096
#define PATH_SIZE 128

int main(int argc, char**argv)
{
  int listenfd, connfd, val = 1;
  char recvline[MAXLINE];
  struct sockaddr_in servaddr;
  
  signal(SIGCHLD, SIG_IGN);
  
  if ((listenfd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL)) < 0)
  {
	perror("socket");
	exit(EXIT_FAILURE);
  }
  
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
  
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(PORT);
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  
  if ((bind(listenfd, (const struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
  {
	perror("bind");
	exit(EXIT_FAILURE);
  }
  
  if ((listen(listenfd, 5)) < 0)
  {
	perror("listen");
	exit(EXIT_FAILURE);
  }
  
  for (;;)
  {
	connfd = accept(listenfd, NULL, NULL);
	
	if (fork())
	{
	  close(connfd);
	}
	else
	{
	  int n = 0, i = 0;
	  char filename[PATH_SIZE];
	  FILE *fd = NULL;
	  char err_msg[] = "Could not open ";
	  char newline[] = "\n";
	  
	  close(listenfd);
	  
	  while ((n = read(connfd, &filename[i], (PATH_SIZE - i))) > 0)
	  {
		i += n;
	  }
	  filename[i] = '\0';
	  
	  if (!(fd = fopen(filename, "r")))
	  {
		write(connfd, err_msg, strlen(err_msg));
		write(connfd, filename, strlen(filename));
		write(connfd, newline, strlen(newline));
		exit(EXIT_FAILURE);
	  }
	  
	  while ((write(connfd, recvline, fread(recvline, sizeof(char), MAXLINE, fd))))
	  {}
	  
	  fclose(fd);
	  close(connfd);
	  exit(EXIT_SUCCESS);
	}
  }
  return EXIT_SUCCESS;
}

Compile and run this code like so... Open a console an type

./server&

Open another console and type

./client 127.0.0.1 filename

Can I recommend some books on this subject? Try these books

Internetworking With TCP/IP Volume III: Client-Server Programming and Applications, Linux/POSIX Socket - Excellent book.

Unix Network Programming - The first half of the book is great, the second half - well the wheels kind fall off in the second half of the book.

This subject(network programming)is none intuitive, you must get a good text on the subject.

@moroccanplaya

Gerard is opening the file in r mode while you are opening the file in rb mode. Could this be an issue ?

@abhimanipal i have tried both, i still get the same issue ?

all i want to do is when i type in localhost at the browser a html page is served

i want to know how does the browser works does it request a filename from the browser ? or does the server just serves the index page when the browser has connected ?

@moroccanplaya

Gerard is opening the file in r mode while you are opening the file in rb mode. Could this be an issue ?

I'm pretty sure Linux doesn't distinguish between binary and text files.

The mode string can also include the letter 'b' either as a last
character or as a character between the characters in any of the
two-character strings described above. This is strictly for com‐
patibility with C89 and has no effect; the 'b' is ignored on all
POSIX conforming systems, including Linux. (Other systems may
treat text files and binary files differently, and adding the 'b'
may be a good idea if you do I/O to a binary file and expect that
your program may be ported to non-Unix environments.)

all i want to do is when i type in localhost at the browser a html page is served

i want to know how does the browser works does it request a filename from the browser ? or does the server just serves the index page when the browser has connected ?

Basically, you pass a URL(Uniform Resource Locator) to a web server which uses this to find the resource...http://en.wikipedia.org/wiki/Uniform_Resource_Locator

The code I posted, does it work? Can you request and get the text file contents?

i have used the code but i only get this at the browser ? im still having trouble writing my html file to the socket.

GET / HTTP/1.1
Host: localhost:50000
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.16) Gecko/20110323 Ubuntu/10

i changed my code to this

n = read(connectfd, buffer, 255 );
	 	if (n < 0) error("ERROR reading from socket");
	 	 printf("Here is the message: %s\n",buffer);
	 	  FILE *open = NULL;
	 	  char err_msg[] = "Could not open";
	 	  
	while((open = fopen("/home/rocco/ww/home.html","r") != EOF))
	{
		n=write(connectfd, &open,1);
		}
			
}

now i just get a bin file trying to be downloaded any ideas why

i am writing a web server thats serves one html file but when i go to my browser and type in localhost:50000/home/user/www/index.html i get something like this

viewd on my browser

heres my code for writing to a socket

n = read(connectfd, buffer, 255 );
	 	if (n < 0) error("ERROR reading from socket");
	 	 printf("Here is the message: %s\n",buffer);
	 	  FILE *open = NULL;
	 	  char err_msg[] = "Could not open";
	 	  
	while((open = fopen("/home/rocco/ww/home.html","r") != EOF))
	{
		n=write(connectfd, &open,1);
		}
			
}

i get a load of 00000 the browser trys to view a binary file

i changed n=write(connectfd, &open,1 to n=write(connectfd, buffer,1 i get a connection but it just waits and does nothing

i am writing a web server thats serves one html file but when i go to my browser and type in localhost:50000/home/user/www/index.html i get something like this

viewd on my browser

heres my code for writing to a socket

n = read(connectfd, buffer, 255 );
	 	if (n < 0) error("ERROR reading from socket");
	 	 printf("Here is the message: %s\n",buffer);
	 	  FILE *open = NULL;
	 	  char err_msg[] = "Could not open";
	 	  
	while((open = fopen("/home/rocco/ww/home.html","r") != EOF))
	{
		n=write(connectfd, &open,1);
		}
			
}

To write a web server, you have to be intimately familiar with the HTTP protocol and how to write client/server applications. I would suggest, learning TCP/IP programming and then concentrate on the HTTP protocol.

What is the input that you are giving to the client and the server programs

@abhimanipal i have re done the code from scratch

i have created the socket, checked if the socket is ok, binded the socket, checked if the binding is ok, listen for connection, checked if the listning is ok, and accept connection and check if the accepting is ok.

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PEND 10


int main(int argc, char *argv[])
{
	/* listen on listen_fd, new connection on new_fd */
	int listen_fd, new_fd;
	/* my address information, address where I run this program */
	struct sockaddr_in my_addr;
	/* remote address information */
	struct sockaddr_in there_addr;
	int size;
	int port;
	
	
	
	if (argc < 2) 
{
        	 printf(stderr,"ERROR, no port provided\n");
        	 exit(1)
}


	lisen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
{
 		 perror("socket error!");
  		 exit(1);
}
	
	else
  	printf("socket is OK\n");
  	
  	/* pass port through command line */
  	port = atoi(argv[1]);
  	/* host byte order */
	my_addr.sin_family = AF_INET;
	/* network byte order */
	my_addr.sin_port = htons(port);
	/* use my IP address */
	my_addr.sin_addr.s_addr = INADDR_ANY;	
	
	memset(&(my_addr.sin_zero), 0, 8);
	
	if(bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
 	 perror("bind error!");
  	 exit(1);
}

	else
	printf("bind is OK...\n");

	if(listen(listen_fd, PEND) == -1)
{

 	 perror("listen error!");
  	 exit(1);
}

	else
	printf("listen is OK...\n");

	size = sizeof(struct sockaddr_in);
	new_fd = accept(listen_fd, (struct sockaddr *)&there_addr, &size);

	if(new_fd == -1)
	perror("accept error!");

	else
  	printf("accept is OK...\n");
  
   	close(new_fd);
	close(listen_fd);
	return 0;
}

now i want to send my html file thats on my filesystem through the socket and i do not know how to go about that. i know i have to accept read then write but i do not know how to put that in practice.

i can send a message

char *msg = "GET %s HTTP/1.0\r\nHOST:%s \r\n\r\n";
	int len; 
	int bytes_sent;
	len = strlen(msg);
	
	
	
 	while(len != bytes_sent)
{
		
		bytes_sent = send(new_fd,msg,len,0);
} 
   	close(new_fd);
	close(listen_fd);
	return 0;
}

just dont know how to go about sending a file ?

Are you sure your message is going correctly ?

If yes then sending a file should not be difficult .
Step 1 read the file into memory and the send the memory contents the same way you sent the message . Don't take the file name from the client as of now. Just send the contents of a file whose location you are sure of

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.