A Simple Http Server with Java/Socket?

79,074

Solution 1

In addition to the \r\n after every request header line, you have to send an empty line after the header. Example:

out.write("HTTP/1.0 200 OK\r\n");
// Header...
out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
out.write("\r\n"); // The content starts afters this empty line
out.write("<TITLE>Hello!</TITLE>");
// Content...

I corrected your code so that it works (but it is still not perfect, you should handle every request in a seperate thread, e.g. with java.util.concurrent.ThreadPoolExecutor):

public static void main(String[] args) throws Exception {
    // création de la socket
    int port = 1989;
    ServerSocket serverSocket = new ServerSocket(port);
    System.err.println("Serveur lancé sur le port : " + port);

    // repeatedly wait for connections, and process
    while (true) {
        // on reste bloqué sur l'attente d'une demande client
        Socket clientSocket = serverSocket.accept();
        System.err.println("Nouveau client connecté");

        // on ouvre un flux de converation

        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

        // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur
        // le flux d'écriture.
        // la donnée lue est donc retournée exactement au même client.
        String s;
        while ((s = in.readLine()) != null) {
            System.out.println(s);
            if (s.isEmpty()) {
                break;
            }
        }

        out.write("HTTP/1.0 200 OK\r\n");
        out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n");
        out.write("Server: Apache/0.8.4\r\n");
        out.write("Content-Type: text/html\r\n");
        out.write("Content-Length: 59\r\n");
        out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n");
        out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
        out.write("\r\n");
        out.write("<TITLE>Exemple</TITLE>");
        out.write("<P>Ceci est une page d'exemple.</P>");

        // on ferme les flux.
        System.err.println("Connexion avec le client terminée");
        out.close();
        in.close();
        clientSocket.close();
    }
}

Solution 2

This is an answer to your last question only and the reason that nothing is visible in the browser is because you calculated the number of characters incorrectly.

It should be 57 instead of 59.

Better yet is to have the number of characters calculated automatically but I believe that your sample is just a sample.

Solution 3

What machine are you using? What OS? If you're running a UNIX machine, then println won't work because it only sends a LF character. HTTP require CR and LF for its headers. Try adding \r to the end of your strings and see if that works.

Oh, also, your:

  out.println("HTTP/1.0 200 OK"+
"Date: Fri, 31 Dec 1999 23:59:59 GMT"+
"Server: Apache/0.8.4"+
"Content-Type: text/html"+
"Content-Length: 59"+
"Expires: Sat, 01 Jan 2000 00:59:59 GMT"+
"Last-modified: Fri, 09 Aug 1996 14:21:40 GMT"+

It's printing a single, long string.

Change those to a println for each string, or add \r\n in to the string.

Solution 4

You need the correct line separators (\r\n) between each line output. It is not enough to just concatenate them - which you can see if you print the response out.

Solution 5

Just a reminder: this is not an HTTP server, as the title would suggest. It is a socket that writes out one specific hard-coded HTTP response (assuming it is fixed according to suggestions in the other answers). Even if you changed the returned content and content length header dynamically, that's still not enough to be compliant with the HTTP protocol.

As I learned the hard way while writing JLHTTP, There's a lot more to HTTP than that. It's not that it's very complicated, but just that there are a lot of additional details and requirements to be properly handled. You can read the RFCs (the core protocol is defined in RFC 7230, or the older RFC 2616) to learn more about what this entails.

I can also offer up the JLHTTP source code as a reference for a well-documented minimal compliant implementation of an HTTP server - it is one file, currently ~3K lines of which almost half are documentation. Its goal is to be tiny, but compliant. I think looking at the code can be useful for anyone wanting to learn what an HTTP server has to do. As I said - not very complicated, but with a lot of little details.

Actually, to be exact, JLHTTP is not as minimal as possible - it does include a few useful extra features, like handling multipart form data for file uploads or supporting HTTPS, which are not required by the HTTP protocol itself. But you can easily rip those parts out (or just skip them) and arrive at a truly minimal Java HTTP server implementation.

Share:
79,074
Marwen Trabelsi
Author by

Marwen Trabelsi

The important thing is not to stop questioning. Don't be afraid to ask the stupid questions : a good programmer will adopt the mindset of being dumb. He will start asking the most simple and child-like questions. My linkedIn

Updated on April 07, 2020

Comments

  • Marwen Trabelsi
    Marwen Trabelsi about 4 years

    I am currently creating a small HTTP server that returns a static page <p>Hello!</p>... I tried with sockets with Java:

      public static void main(String[] args) throws Exception {
    
            // création de la socket
            int port = 1989;
            ServerSocket serverSocket = new ServerSocket(port);
            System.err.println("Serveur lancé sur le port : " + port);
    
            // repeatedly wait for connections, and process
            while (true) {
    
                // on reste bloqué sur l'attente d'une demande client
                Socket clientSocket = serverSocket.accept();
                System.err.println("Nouveau client connecté");
    
                // on ouvre un flux de converation
    
               BufferedReader in = new BufferedReader(
                               new InputStreamReader(clientSocket.getInputStream())
                              ); 
                PrintWriter out = new PrintWriter(
                             new BufferedWriter(
                                new OutputStreamWriter(clientSocket.getOutputStream())), 
                             true);   
    
                // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur le flux d'écriture.
                // la donnée lue est donc retournée exactement au même client.
                String s;
                while ((s = in.readLine()) != null) {
                    System.out.println(s);
    
    
           out.write("HTTP/1.0 200 OK\r\n");
           out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n");
           out.write("Server: Apache/0.8.4\r\n");
           out.write("Content-Type: text/html\r\n");
           out.write("Content-Length: 59\r\n");
           out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n");
           out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
           out.write("\r\n");
           out.write("<TITLE>Exemple</TITLE>");
           out.write("<P>Ceci est une page d'exemple.</P>");
      }
    
                // on ferme les flux.
                System.err.println("Connexion avec le client terminée");
                out.close();
                in.close();
                clientSocket.close();
            }
        }
    

    this code does not contain any errors and I got a response from the browser like this:

    GET / HTTP/1.1
    Host: localhost:1989
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Comodo_Dragon/19.0.3.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
    

    But my problem is that I get no page at the Browser? Any help please?

    PS: I already read this article: http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol , (im sorry for the french language...)