By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,759 Members | 1,727 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,759 IT Pros & Developers. It's quick & easy.

HTTP Server Response Headers

P: 12
Hi i need to make a BASIC HTTP server for a project using JUST TCP/IP Sockets so please don't suggest anything that would use some of C#'s higher level networking components, Thanks =).

Anyway my problem:

i have created the server and it all works so far but i haven't implemented the HTTP Headers properly, if i leave out all the headers i wrote then some browsers work fine with it (can't remember which) but when i add in the headers (and change them around trying to get it to work) it only shows part of the page or doesn't load the css file and once it just showed half of the html code!

btw i dont know if this makes a difference but i use the link tag in my main.html head to get the css file.
<link rel="stylesheet" type="text/css" href="mainStylesheet.css"/>

and before anyone asks, the html file works fine if i just run it straight on the browser! =P

Here is some of my code:
Expand|Select|Wrap|Line Numbers
  1. class ConnectionThread
  2.     {
  3.         public ConnectionThread(Socket socket)
  4.         {
  5.             connection = socket;
  6.         }
  7.  
  8.         Socket connection = null;
  9.         NetworkStream mainStream = null;
  10.         BinaryReader inStream = null;
  11.         BinaryWriter outStream = null;
  12.  
  13.         public void run()
  14.         {
  15.             mainStream = new NetworkStream(connection);
  16.  
  17.             inStream = new BinaryReader(mainStream);
  18.             outStream = new BinaryWriter(mainStream);
  19.  
  20.             byte b = 0;
  21.             string s = "";
  22.             string[] requestData = null;
  23.             string requestedPage = null;
  24.  
  25.             try
  26.             {
  27.                 while (mainStream.DataAvailable)
  28.                 {
  29.                     b = inStream.ReadByte();
  30.                     s += (char)b;
  31.                 }
  32.  
  33.                 requestData = s.Split('\r');
  34.  
  35.                 int l = requestData.Length;
  36.  
  37.                 //check to see if it got the request data (sometimes it doesn't)
  38.                 if (l > 1) 
  39.                 {
  40.                     //get the page the browser requests
  41.                     requestedPage = requestData[0].Split(' ')[1];
  42.  
  43.                     //calls the method which sends the browser the page to be displayed
  44.                     theSwitch(requestedPage);
  45.                 }
  46.                 else
  47.                 {
  48.                     //call method again to try and get the request data
  49.                     run();
  50.                 }
  51.             }            
  52.             catch (Exception exp)
  53.             {
  54.                 Console.WriteLine("Unexpected error.");
  55.                 Console.WriteLine("Error caused by: " + exp.Message);                
  56.             }
  57.         }
  58.  
  59.         void theSwitch(string item)
  60.         {
  61.             string file = null;
  62.             char[] output = null;
  63.             string head = null;
  64.  
  65.             try
  66.             {
  67.                 switch (item)
  68.                 {
  69.                     case "/":
  70.  
  71.                         file = readFile("Resources/main.html");
  72.  
  73.                         head += "HTTP/1.1 100 Continue\r\n";
  74.                         head += String.Format("{0:ddd, dd MMM yy HH:mm:ss} GMT\r\n", DateTime.Now);
  75.                         head += "Server: Ollie's Server v1.0\r\n";
  76.                         head += "Cache-Control: none\r\n";
  77.                         head += "Content-Type: text/html\r\n";
  78.                         head += string.Format("Content-Length: {0}\r\n", file.Length);
  79.                         head += "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n";
  80.  
  81.                         Console.WriteLine(head);
  82.                         output = (head + file).ToArray();
  83.  
  84.                         outStream.Write(output);
  85.  
  86.                         break;
  87.  
  88.                     case "Resources/mainStylesheet.css":
  89.  
  90.                         file = readFile("/mainStylesheet.css");
  91.  
  92.                         head += "HTTP/ 1.1 100 Continue\r\n";
  93.                         head += String.Format("{0:ddd, dd MMM yy HH:mm:ss} GMT\r\n", DateTime.Now);
  94.                         head += "Server: Ollie's Server v1.0\r\n";
  95.                         head += "Cache-Control: none\r\n";
  96.                         head += "Content-Type: text/css\r\n";
  97.                         head += string.Format("Content-Length: {0}\r\n", file.Length);
  98.  
  99.                         output = (head + file).ToArray();
  100.  
  101.                         outStream.Write(file);
  102.  
  103.                         break;
  104.  
  105.                     case "Resources/favicon.ico":
  106.  
  107.                         MemoryStream ms = new MemoryStream();
  108.                         System.Drawing.Image i = System.Drawing.Image.FromFile("Resources/favicon.gif");
  109.                         i.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
  110.  
  111.                         head += "HTTP/1.1 206 Partial content";
  112.                         head += String.Format("{0:ddd, dd MMM yy HH:mm:ss} GMT\r\n", DateTime.Now);
  113.                         head += "Server: Ollie's Server v1.0\r\n";
  114.                         head += "Cache-Control: none\r\n";
  115.                         head += "Content-Type: image/gif\r\n";
  116.                         head += string.Format("Content-Length: {0}\r\n", ms.Length);
  117.  
  118.                         output = (head + ms).ToArray();
  119.  
  120.                         outStream.Write(output);
  121.  
  122.                         break;
  123.  
  124.                     default:
  125.  
  126.                         Console.WriteLine("Not Found");
  127.                         Console.WriteLine();
  128.  
  129.                         break;
  130.                 }
  131.  
  132.                 inStream.Close();
  133.  
  134.                 outStream.Flush();
  135.                 outStream.Close();
  136.  
  137.                 mainStream.Close();
  138.  
  139.                 connection.Close();
  140.  
  141.             }
  142.             catch (Exception exp)
  143.             {
  144.                 Console.WriteLine("Unexpected error.");
  145.                 Console.WriteLine("Error caused by: " + exp.Message);
  146.             }
  147.         }
  148.  
  149.         //method that returns a string of the html or css file to be sent to the browser
  150.         private string readFile(string file)
  151.         {
  152.             string output = null;
  153.  
  154.             try
  155.             {
  156.                 StreamReader reader = new StreamReader(file);
  157.                 while (!reader.EndOfStream)
  158.                 {
  159.                     output += reader.ReadToEnd();
  160.                 }
  161.             }
  162.             catch (Exception exp)
  163.             {
  164.                 Console.WriteLine(exp.ToString());
  165.             }
  166.  
  167.             return output;
  168.         }
  169.     }
  170. }
So i guess my question is what is the correct http headers to use here and also which headers are compulsory and which are just optional?

i would also like to use the ETag, Accept and Connection header(s) so any info you can supply on them would be greatly appreciated!

Thanks in advance! =)
Ollie
Apr 13 '11 #1

✓ answered by Oralloy

The basic server mechanism is fairly simple, no?

A query consists of
1) The basic query line (GET, POST, etc.)
2) The headers (header: values)
3) A blank line
4) The body of the query (arbitrary, see Content-Type header)

So your first parse of the query should give you that break down.

The headers are unordered, so you can just put them into a map, and retrieve them at will. Do you know the strict specification for headers?

If I remember correctly, the blank line and body are optional.

If you have a failed parse, then your response looks something like this:
Expand|Select|Wrap|Line Numbers
  1. HTTP/1.1 400 Bad Request
  2. Connection: close
  3. Server: Jetty(6.1.16)
  4.  
  5.  
The hard part comes with how you process after you parse the query components.

First off, you have to sanity check the basic headers. If any are wrong, throw an error.

Next, since the query is valid, you hand it off to the query processor.

The query processor generates its response and hands it back to the main server.

Then, the main server constructs the formatted response and sends it to the client.

One really good way to test is to use Telnet to link to your server. You can try it fairly easily under windows; use: telnet www.microsoft.com 80

So, all that said, where is your server breaking down?

Share this Question
Share on Google+
2 Replies


Oralloy
Expert 100+
P: 983
The basic server mechanism is fairly simple, no?

A query consists of
1) The basic query line (GET, POST, etc.)
2) The headers (header: values)
3) A blank line
4) The body of the query (arbitrary, see Content-Type header)

So your first parse of the query should give you that break down.

The headers are unordered, so you can just put them into a map, and retrieve them at will. Do you know the strict specification for headers?

If I remember correctly, the blank line and body are optional.

If you have a failed parse, then your response looks something like this:
Expand|Select|Wrap|Line Numbers
  1. HTTP/1.1 400 Bad Request
  2. Connection: close
  3. Server: Jetty(6.1.16)
  4.  
  5.  
The hard part comes with how you process after you parse the query components.

First off, you have to sanity check the basic headers. If any are wrong, throw an error.

Next, since the query is valid, you hand it off to the query processor.

The query processor generates its response and hands it back to the main server.

Then, the main server constructs the formatted response and sends it to the client.

One really good way to test is to use Telnet to link to your server. You can try it fairly easily under windows; use: telnet www.microsoft.com 80

So, all that said, where is your server breaking down?
Apr 13 '11 #2

P: 12
Yer its all very simple which i why i was confused as to why it wasn't working so i asked here for some help.

It was blank line that i had missing which was making it not work properly, thanks for your help! =)

and i know about the bad request just i hadn't got round to doing that yet, was trying to make the damn thing work first!! =P
Apr 14 '11 #3

Post your reply

Sign in to post your reply or Sign up for a free account.