TCPは、ポートへのアクティブな接続や、これからクローズする接続があるときは、リッスンしているポートの再利用ができません。サーバの接続のクローズ処理は、プロトコルを最後まで正しく実行するために2分ぐらいかかります。サーバの起動や停止を繰り返す場合に、ローカルポートを再利用するオプションが指定できます。
this.server = new ServerSocket(); this.server.setReuseAddress(true); // ローカルポートの再利用 this.server.bind(new InetSocketAddress(port));
これを踏まえると、TcpServerは
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; public class TcpServer { private static final int DEFOULT_PORT = 1000; private ServerSocket server; public TcpServer() throws IOException { this(DEFOULT_PORT); } public TcpServer(int port) throws IOException { this.server = new ServerSocket(); this.server.setReuseAddress(true); this.server.bind(new InetSocketAddress(port)); } public void start() { new Thread() { @Override public void run() { while(true) { try { Socket socket = server.accept(); // block new Thread(new ConnectionHandler(socket)).start(); } catch (SocketException e) { if (e.getMessage().equalsIgnoreCase("Socket closed")) { System.out.println("Socket closed"); break; } e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } class ConnectionHandler implements Runnable { private final Socket socket; public ConnectionHandler(final Socket socket) { this.socket = socket; } @Override public void run() { System.out.println("accepted " + socket.getInetAddress() + ":" + socket.getPort()); try { socket.setTcpNoDelay(true); } catch (SocketException e) { // do nothing } try { handleConversation(); } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } void handleConversation() throws IOException { InputStream in = new BufferedInputStream(socket.getInputStream()); OutputStream out = new BufferedOutputStream(socket.getOutputStream()); byte[] buffer = new byte[8192]; int count; while((count = in.read(buffer)) >= 0) { System.out.println("received " + count + " bytes from " + socket.getInetAddress() + ":" + socket.getPort()); System.out.println(new String(buffer).trim()); out.write(buffer, 0, count); out.flush(); } socket.shutdownOutput(); // half close } } public static void main(String[] args) throws Exception { TcpServer tcpServer = new TcpServer(); tcpServer.start(); } }