以下代码运行了1个小时,然后关闭:
public class Mp extends JWindow implements MouseListener, MouseMotionListener { public static Mp j; private int serverPort = 0; private ServerSocket serverSock = null; private Socket sock = null; public static void main(final String[] args) throws IOException, InterruptedException, Exception { j = new Mp(); j.setVisible(true); j.waitForConnections(); } public void waitForConnections() { while (true) { try { sock = serverSock.accept(); System.out.println("[TCPMediaHandler]: Accepted new socket"); TCPMediaHandler handler = new TCPMediaHandler(sock); handler.start(); } catch (IOException e) { e.printStackTrace(System.err); } } } public Mp() throws IOException { this.serverPort = 38891; serverSock = new ServerSocket(serverPort); serverSock.setReuseAddress(true); //serverSock.setSoTimeout(500); //serverSock.setSoLinger(true, 0); System.out.println("[TCPMediaHandler]: Server started"); this.v1.setBackground(Color.BLACK); this.v1.addMouseListener(this); /* Close the window */ this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { System.exit(0); } }); }
当我重新运行同一件事时,它失败了java.net.BindException:
java.net.BindException
$ java -cp /var/tmp/dist/Mp.jar test.Mp Exception in thread "main" java.net.BindException: Address already in use at java.net.PlainSocketImpl.socketBind(Native Method) at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:353) at java.net.ServerSocket.bind(ServerSocket.java:336) at java.net.ServerSocket.<init>(ServerSocket.java:202) at java.net.ServerSocket.<init>(ServerSocket.java:114) at test.Mp.<init>(Mp.java) at test.Mp.main(Mp.java)
大约需要3至4分钟才能再次成功执行。关闭后如何使它立即工作?
跟进:
$ netstat | grep 38891 tcp 35 0 localhost:38891 localhost:37842 CLOSE_WAIT tcp 0 0 localhost:34955 localhost:38891 ESTABLISHED tcp 32 0 localhost:38891 localhost:37824 CLOSE_WAIT tcp 0 0 localhost:38891 localhost:34955 ESTABLISHED $ lsof -w -n -i tcp:38891 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME xdg-scree 5254 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN) xdg-scree 5355 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN) xdg-scree 5455 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN) telnet 7058 sun 3u IPv4 242987 0t0 TCP 127.0.0.1:34955->127.0.0.1:38891 (ESTABLISHED) sleep 9002 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN) sleep 9005 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN) sleep 9008 sun 29u IPv4 231948 0t0 TCP *:38891 (LISTEN)
您会看到setReuseAddress(true)的调用为时已晚,即在绑定引发异常之后。
您可以通过三个步骤创建一个未绑定的ServerSocket,使其可重用,然后将其绑定。
ServerSocket ss = new ServerSocket(); ss.setReuseAddress(true); ss.bind(new InetSocketAddress(12345));