【问题标题】:Java server socket doesn't reuse addressJava服务器套接字不重用地址
【发布时间】:2012-05-09 12:24:50
【问题描述】:

我在 linux 中使用服务器套接字,我需要在 time_wait TCP 状态到期之前将其关闭并重新打开。我在绑定之前设置了服务器套接字的重用地址选项,但它仍然抛出 BindException。 我也试过这个http://meteatamel.wordpress.com/2010/12/01/socket-reuseaddress-property-and-linux/,但还是不行。

要打开我使用的服务器套接字:

ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(12345));

然后关闭:

ss.close();

在绑定调用时抛出“地址已在使用”BindException。

此代码生成异常:

for (int i = 0; i < 2; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final ServerSocket ss = new ServerSocket();
                    ss.setReuseAddress(true);
                    ss.bind(new InetSocketAddress(12345));
                    Socket s = ss.accept();
                    System.out.println((char) s.getInputStream().read());
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        Thread.sleep(500);
        Socket s = new Socket("localhost", 12345);
        s.getOutputStream().write('c');
    }

【问题讨论】:

  • 你能编辑你的问题并向我们展示你用来配置套接字的代码吗?

标签: java serversocket time-wait


【解决方案1】:

你设置重用之前绑定不是在你得到异常之后。

ServerSocket ss = new ServerSocket(); // don't bind just yet
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(12345)); // can bind with reuse= true

这在 Windows 7 和 RHEL 5.x 上运行没有错误

for (int i = 0; i < 1000; i++) {
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                final ServerSocket ss = new ServerSocket();
                ss.setReuseAddress(true);
                ss.bind(new InetSocketAddress(12345));
                Socket s = ss.accept();
                System.out.println((char) s.getInputStream().read());
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    t.start();
    Thread.sleep(50);
    Socket s = new Socket("localhost", 12345);
    s.getOutputStream().write('c');
    t.join();
}

【讨论】:

  • 我在 windows 和 linux 上试了 100,000 次,但没有错误。 :P
  • 当然可以,但是您的代码没有建立 TCP 连接,因此没有处于时间等待状态的连接。 (在主帖中尝试测试代码)
  • 您没有确保在开始新的服务器套接字之前关闭您的服务器套接字。
  • 好的,我解决了,是程序逻辑问题。服务器套接字关闭方法没有在正确的时间调用,还是谢谢你。
【解决方案2】:

你必须这样做:这意味着提取代码以便它不会不断重复

public class....

private ServerSocket socServer;

onCreate
...

try {
    socServer = new ServerSocket();
    socServer.setReuseAddress(true);
    socServer.bind(new InetSocketAddress(SERVER_PORT));
} catch (IOException e) {
 e.printStackTrace();
}

// New thread to listen to incoming connections
new Thread(new Runnable() {
    @Override
    public void run() {
        try 
        {
            // Create server side client socket reference
            Socket socClient = null;

            // Infinite loop will listen for client requests to connect
            while (true) {
                // Accept the client connection and hand over communication 
                // to server side client socket
                   socClient = socServer.accept();

               // For each client new instance of AsyncTask will be created
                  ServerAsyncTask serverAsyncTask = new ServerAsyncTask();

               // Start the AsyncTask execution 
               // Accepted client socket object will pass as the parameter
               serverAsyncTask.execute(new Socket[] {socClient});
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 2011-09-27
    • 2011-11-28
    相关资源
    最近更新 更多