In these days I feel comfortable Spring, but it has been suddenly very cold from last week. That's why I have a sore throat.
By the way, I don't know why, but I have to implement a server from scratch using sockets recently. So I write about how to implement TCP server in Java, in addition to organizing my ideas.
There are three ways to handle server sockets in Java SE 7.
At first we should start from basic point. Let's try writing echo-server using ordinary socket API that was already active when I was high school student. Although it's called "ordinary socket API", the others also handle "ordinary socket" but in defferent way.
This API is very simple. See following code.
try (ServerSocket listener = new ServerSocket();) { listener.setReuseAddress(true); listener.bind(new InetSocketAddress(8080)); System.out.println("Server listening on port 8080..."); while (true) { try (Socket socket = listener.accept();) { InputStream from = socket.getInputStream(); OutputStream to = socket.getOutputStream(); Bytes.copy(from, to); } } } catch (IOException e) { e.printStackTrace(); }
The proccess is,
Then, run this.
$ java SocketServer Server listening on port 8080...
Good, our server is running. Let's try connecting from another terminal.
$ telnet localhost 8080 Trying ::1... Connected to localhost. Escape character is '^]'.
It's OK. Now we have a connection to our server. Input something to the terminal, and get output as is. Congratulations! ...But this server has a big problem.
The problem is that the server can handle only one connection at the same time. To get it, connect from some terminals. The others' connections are not handled unless one's is closed.
That's because we handle a Socket one by one in the previous code. Therefore, we make it multithreaded.
ExecutorService worker = Executors.newCachedThreadPool(); try (ServerSocket listener = new ServerSocket();) { listener.setReuseAddress(true); listener.bind(new InetSocketAddress(8081)); System.out.println("Server listening on port 8081..."); while (true) { final Socket socket = listener.accept(); worker.submit(new Runnable() { @Override public void run() { try { InputStream from = socket.getInputStream(); OutputStream to = socket.getOutputStream(); Bytes.copy(from, to); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { } } } }); } } catch (IOException e) { e.printStackTrace(); } finally { worker.shutdown(); }
It's done. Now we have a very practical echo-server which is able to handle connections at the same time.
Do you have peace of mind? It's too early. Remember that there are the two other ways to handle server sockets. They have some good points which this "ordinary socket API" don't have. (But also have some bad points) Next time, let's check how to use the second, "Non-blocking" API.