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;

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;
}

Edited 5 Years Ago by gerard4143: n/a

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.

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);
		}

Edited 5 Years Ago by moroccanplaya: n/a

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.

Edited 5 Years Ago by gerard4143: n/a

@moroccanplaya

Gerard is opening the file in r mode while you are opening the file in rb mode. Could this be an 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.)

Edited 5 Years Ago by gerard4143: n/a

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 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.

@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;
}

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

This article has been dead for over six months. Start a new discussion instead.