0

I am creating a multithread server program to display the browser's request when it try to connect to localhost.

I found only IE9 on my Windows works as expected but not Firefox 19, Chrome, Opera. The are simply sitting there to wait for my program response.

What I have missed?

import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HTTPEchoServer {

    private static final String serverName = "HTTPEchoServer";
    private static final int port = 80;
    private static final String CRLF = "\r\n";
    private static final Logger logger = Logger.getLogger(serverName);

    private static void printHeader(PrintWriter out) {
        out.println("HTTP/1.0 200 OK\r\n" + "Server: " + serverName + CRLF
                + "Content-Type: text/html" + CRLF + CRLF
                + "<!DOCTYPE HTML PUBLIC "
                + "\"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
                + "<HTML>\n"
                + "<HEAD>\n"
                + " <TITLE>" + "HTTP Echo Server Result</TITLE>\n"
                + "</HEAD>\n"
                + "<H1>HTML Received from HTTP Echo Server</H1>\n"
                + "<B>Here is the request sent by your browser:</B>\n"
                + "<PRE>");
    }

    private static void printTrailer(PrintWriter out) {
        out.println("</PRE>\n" + "</BODY>\n" + "</HTML>\n");
    }

    static class ClientHandler extends Thread {

        Socket socket = null;

        public ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {

            logger.log(Level.INFO, "Accepted client {0}:{1}", 
                  new Object[]{socket.getInetAddress(), socket.getPort()});
            try {

                InputStream is = socket.getInputStream();
                OutputStream os = socket.getOutputStream();
                try (PrintWriter writer = new PrintWriter(os, true)) {
                    synchronized (this) {
                        printHeader(writer);
                        writer.flush();
                        BufferedReader reader = new BufferedReader 
                             (new InputStreamReader(is));
                        String line;
                        while ((line = reader.readLine()) != null) {
                            writer.println(line);
                            writer.flush();
                        }
                        printTrailer(writer);
                        writer.flush();
                        writer.close();
                    }
                }
                socket.close();
            } catch (IOException ex) {
                logger.log(Level.SEVERE, null, ex);
            }
            logger.log(Level.INFO, "Disconnected client {0}:{1}",
new Object[]{socket.getInetAddress(), socket.getPort()});
        }
    }

    public static void main(String[] args) {    

        try {
            ServerSocket server = new ServerSocket(port);
            logger.log(Level.INFO, "Server started, listening at port {0} ...", port);
            ExecutorService executor = Executors.newCachedThreadPool();
            while (true) {
                Socket socket = server.accept();
                ClientHandler handler = new ClientHandler(socket);
                executor.execute(handler);
            }
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }
}    

Also, I found I cannot run this program on the OS X unless I change the port to 8080. I have already disabled the firewall on my OS X 10.8.2 computer. The error I get is:

<pre>
java.net.BindException: Permission denied
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.<init>(ServerSocket.java:237)
    at java.net.ServerSocket.<init>(ServerSocket.java:128)
    at HTTPEcho.HTTPEchoServer.main(HTTPEchoServer.java:80)
</pre>
  • 1
    Ports below 1024 are privileged, you need to be (suid) root to bind to them, cf. [this Q&A](http://stackoverflow.com/questions/10182798/why-are-ports-below-1024-privileged). – Anders R. Bystrup Feb 26 '13 at 10:08

3 Answers3

2

You cannot open server socket in applet in all browsers except MSIE. This is done because opening server socket is security violation. If you do want to do this you have to sign your applet.

I hope that I understood your correctly that your code is running in applet environment (because you mentioned browsers) although I cannot see this facet from your stack trace that starts from main().

EDIT: I read your post again and understood that your question actually contains 2 questions: first about applets and second about running as application under Unix. For unix @Anders R. Bystrup gave you the answer: only root can listen to ports under 1024. So, you have to run your program as root or using sudo.

BTW it seems that you are on the wrong way. Could you probably explain what would you like to achieve and community probably can give you a tip for better solution.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • @Esailija, I agree with you. This is the reason I said that he probably on a wrong way for various reasons. – AlexR Feb 26 '13 at 10:15
  • Hello AlexR, Thanks for your reply. 1. I just run my code inside NetBeans (NetBeans 7.3, Java 1.7.0_15) and not applet. In addition, I just tried to run the code from the terminal and found the result is the same. 2. Yes, the SU works as expected. – Joshua Chung Feb 26 '13 at 15:34
  • > Could you probably explain what would you like to achieve... Just a command line program which echo any http client's request header with basic formatting. – Joshua Chung Feb 27 '13 at 04:25
0

As the exception itself says java.net.BindException: Permission denied. You need to be root user to bind ports below 1024. If you are on linux you san do sudo java HTTPEchoServer to start the server.

Other possibility may be that you already have a server running on port 80.

kaysush
  • 4,797
  • 3
  • 27
  • 47
0

Port 80 is reserved HTTP port, there are other ports aswell which are reserved.

ports 1 through 1023 for administrative functions leaving port numbers greater than 1024 available for use.

How to find available port

Community
  • 1
  • 1
TheWhiteRabbit
  • 15,480
  • 4
  • 33
  • 57