Search code examples
javatry-catchserversockettry-with-resources

ServerSocket doesn't work with try-with-resources?


So we're fooling around with ServerSockets in class, making a very simple HTTP server that takes a request, does nothing with it, and responds with a 200 OK followed by some HTML content.

I've been trying to figure out this problem for two days, and I haven't been able to get to grips with it, and neither has my teacher. I've come to think it is a problem with closing the server, for some odd reason. I've fixed the problem, but would just like to know why I happened in the first place.

Here are three snippets:

HttpServer.class:

package httpserver;

import java.io.Closeable;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class HttpServer implements Closeable {
    public static final int PORT = 80;
    public static final int BACKLOG = 1;
    public static final String ROOT_CATALOG = "C:/HttpServer/";

    private ServerSocket server;
    private Socket client;
    private Scanner in;
    private PrintWriter out;

    private String request;

    public HttpServer() throws IOException {
        server = new ServerSocket(PORT, BACKLOG);
    }

    public Socket accept() throws IOException {
        client = server.accept();
        in = new Scanner(client.getInputStream());
        out = new PrintWriter(client.getOutputStream());

        return client;
    }

    public void recieve() {
        request = in.nextLine();
        System.out.println(request);
    }

    public void respond(final String message) {
        out.print(message);
        out.flush();
    }

    @Override
    public void close() throws IOException {
        if(!server.isClosed()) {
            client = null;
            server = null;
        }
    }
}

Main.class solution that works:

package httpserver;

import java.io.IOException;
import java.net.Socket;

public class Main {
    public static void main(String[] args) throws IOException {
        HttpServer server = new HttpServer();
        Socket client;

        while(true) {
            client = server.accept();
            server.recieve();
            server.respond("HTTP/1.0 200 OK\r\n"
                    + "Content-Type: text/html\r\n"
                    + "\r\n"
                    + "<html><body><b>hello..</b></body></html>");
            client.close();
        }
    }
}

Main.class solution that doesn't work:

package httpserver;

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try(HttpServer server = new HttpServer()) {
            while (true) {
                server.accept();
                server.recieve();
                server.respond("HTTP/1.0 200 OK\r\n"
                        + "Content-Type: text/html\r\n"
                        + "\r\n"
                        + "<html><body><b>hello..</b></body></html>");
            }
        } catch(IOException ex) {
            System.out.println("We have a problem: " + ex.getMessage());
        }
    }
}

I could imagine it has something to do with not closing the client socket after each loop iteration. But even so, it should at least go through once, before bugging up in that case. I really can't see what the problem is supposed to be.

No error messages, nothing...


Solution

  • You do not specify any Content-length when sending the HTTP, so the browser does not know when to stop reading for more data. See How to know when HTTP-server is done sending data for more info.

    In the working example you closed the client socket, which tells the browser there is no more data - for your ambitions this might be enough if you don't want the browser to respond.