套接字EADDRINUSE(地址已在使用中)

时间:2014-07-07 16:48:06

标签: android sockets

我正在进行套接字编程。我从下面的链接中获取了参考:

http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/

以下是有关我的问题的详细信息。我已为此ServerThread创建了Android lib(我的项目要求),这在测试应用程序中使用。

现在测试应用程序通过lib连接到此并执行此过程。第一次它完全正常,但如果我关闭并重新打开,它会因异常而崩溃:

  

“EADDRINUSE(地址已在使用中)”

还试过serverSocket.setReuseAddress(true)但没有运气。

我的代码:

public void run() {
    Socket socket = null;
    try {
        serverSocket = new ServerSocket(SERVER_PORT);
        serverSocket.setReuseAddress(true);

    } catch (IOException e) {
        Log.e(TAG, "exception1= " + e.getMessage());
    }
    while (!Thread.currentThread().isInterrupted()) {
        try {

            socket = serverSocket.accept();
            Log.d(TAG, "server Connected.......!!!!");

            communicationThread = new CommunicationThread(
                    socket);
            commThread = new Thread(communicationThread);
            commThread.start();

        } catch (IOException e) {
            Log.e(TAG, "exception 2=" + e.getMessage());
        }
    }
}

如果我呼叫serverSocket.close()我将收到异常2作为服务器套接字关闭。通信线程与前一个链接中给出的相同。

4 个答案:

答案 0 :(得分:25)

在套接字绑定到端口之前,您必须调用setReuseAddress(true)。您之后正在调用它,因为您正在将端口传递给构造函数,构造函数将立即绑定套接字。

请改为尝试:

serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it

答案 1 :(得分:8)

TCP(可能还有其他一些)套接字在关闭后的一段时间内无法重用相同的端口。这是为了防止在现有连接的网络上存在数据时出现混淆。您可以覆盖此行为,但默认设置是在允许重用端口之前等待一段时间。

修复此问题的调用是服务器套接字上的setReuseAddress(true)。但是我不确定它是否需要在第一个套接字或第二个套接字上调用,或者两者都需要。

编辑:

这是一篇博客文章,描述了TCP套接字TIME_WAIT状态及其存在的原因:http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html

答案 2 :(得分:2)

虽然其他答案指出setReuseAddress(true)的重要性,但可能出现的另一个问题是构造ServerSocket两次并使用相同的参数调用bind。例如,如果您调用问题的代码run()两次,serverSocket将被分配给ServerSocket类的新实例,但旧的实例仍然存在,直到收集垃圾。现在使用端口值作为参数构造等于绑定ServerSocket对象,并且最终将绑定到同一地址的两个ServerSocket,这是禁止的异常。所以用你选择的端口只构建一次你的serverSocket!

答案 3 :(得分:0)

尝试在run()方法之外创建SocketServer实例。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)   
    try {
        // create a new instance of an unbound socket first
        serverSocket = new ServerSocket(); 
        } catch (IOException e) {
           e.printStackTrace();
        }
}