【问题标题】:Socket EADDRINUSE (Address already in use)套接字 EADDRINUSE(地址已在使用中)
【发布时间】:2014-07-07 16:48:05
【问题描述】:

我正在做套接字编程。我参考了以下链接:

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

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

现在测试应用程序通过 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。通信线程与上一个链接中给出的相同。

【问题讨论】:

标签: android sockets


【解决方案1】:

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

试试这个:

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

【讨论】:

  • 我试过了,但是我遇到了异常 ServerSocketThread exception 2=Socket is closed
  • 具体在哪一行代码?请更具体。
  • 执行此行时 socket = serverSocket.accept();在while循环内。
  • serverSocket.accept() 不应抛出错误 2,除非调用了 serverSocket.close()。
  • @qwerty Java 文档说无参数构造函数“创建一个 unbound 服务器套接字”,并且没有显示任何接受的单参数构造函数null 作为输入。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 或者,至少 close() 之前的 ServerSocket 在创建一个新的之前。这样,即使前一个习惯已经被 GC 了,它的 socket 也会释放端口,setReuseAddress() 将允许端口在处于 TIME_WAIT 状态时被反弹
    【解决方案4】:

    尝试在 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();
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      相关资源
      最近更新 更多