【问题标题】:TCP Socket IOExceptionbind failed: EADDRINUSE (Address already in use)TCP Socket IOExceptionbind 失败:EADDRINUSE(地址已在使用中)
【发布时间】:2016-05-22 16:19:09
【问题描述】:

看了几篇关于这个错误的帖子后,我真的不明白为什么有时我会收到这个异常

我在这里看到几个帖子建议对绑定套接字进行循环,但我认为它应该执行一次,并且在其他地方有问题。

这是我的代码:

 public ServerNetworkThread()
    {
        setName("ServerNetworkThread");
        _port = Logics.getInstance().getSharedPrefsManager().getInt(SharedPreferencesManager.SERVER_PORT_KEY, Consts.SERVER_PORT);
    }

    public void setHandler(Handler h)
    {
        _handler = h;
    }

    @Override
    public void run()
    {    
        _isWorking = true;
        try
        {
            _serverSocket = new ServerSocket();
            _serverSocket.setReuseAddress(true);
            _serverSocket.bind(new InetSocketAddress(_port));

            while (_isWorking)
            {
                _socket = _serverSocket.accept();
                _socket.setSoTimeout(Consts.CLIENT_SOCKET_TIMEOUT);
                readDataTest();
            }    
        }
        catch (SocketTimeoutException e)
        {
            e.printStackTrace();
            Logger.d("anton", e.getMessage());
        }
        catch (IOException e)
        {
            e.printStackTrace();
            Logger.d("anton", "server thread IOException" + e.getMessage());
        }

    }

    private void readDataTest() throws IOException
    {
        //          BufferedReader inFromClient = new BufferedReader(new InputStreamReader(_socket.getInputStream(),Charset.forName("UTF-16LE")));
         //          BufferedReader inFromClient = new BufferedReader(new InputStreamReader(_socket.getInputStream(),Charset.forName("UTF-16LE")));
        InputStream iStream = _socket.getInputStream();
        InputStreamReader in = new InputStreamReader(iStream, Charset.forName("UTF-16LE"));
        DataOutputStream outToClient = new DataOutputStream(_socket.getOutputStream());
        char[] buf = new char[1024];
        int lettersCount = in.read(buf, 0, buf.length);
        String request = new String(buf,0,lettersCount);
//      request = request.split(Consts.EOF)[0];
        Log.d("test","server got request="+request);

        String responseStr = parseResponse(request);
        byte[] response = responseStr.getBytes("UTF-16LE");
        outToClient.write(response);
        outToClient.flush();
        outToClient.close();
        in.close();
        _socket.close();
    }

这是我的例外:

W/System.err( 1433): java.net.BindException: bind failed: EADDRINUSE (Address already in use)
W/System.err( 1433):    at libcore.io.IoBridge.bind(IoBridge.java:89)
W/System.err( 1433):    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:150)
W/System.err( 1433):    at java.net.ServerSocket.bind(ServerSocket.java:319)
W/System.err( 1433):    at java.net.ServerSocket.bind(ServerSocket.java:282)
W/System.err( 1433):    at com.example.visionixpanel.logics.network.ServerNetworkThread.run(ServerNetworkThread.java:61)
W/System.err( 1433): Caused by: libcore.io.ErrnoException: bind failed: EADDRINUSE (Address already in use)
W/System.err( 1433):    at libcore.io.Posix.bind(Native Method)
W/System.err( 1433):    at libcore.io.ForwardingOs.bind(ForwardingOs.java:40)
W/System.err( 1433):    at libcore.io.IoBridge.bind(IoBridge.java:87)
W/System.err( 1433):    ... 4 more

被这行抛出:

 _serverSocket.bind(new InetSocketAddress(_port));

更新:

我也有这个代码:

public void stopThread()
{
    _isWorking = false;
    try
    {
        if (_serverSocket != null)
        {
            _serverSocket.close();
        }
        if (_socket != null)
        {
            _socket.close();
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

也许与清理线程套接字资源有关?

【问题讨论】:

  • 您尝试使用的端口号或ip地址好像忙!
  • 如果它很忙,我需要做什么?我需要从服务器获得反馈,我可以强制关闭它吗?
  • 我不确定这是否可能。但首先请确保您的 ip 忙。要使用代码执行此操作,请尝试“InetAddress.getByName(host).isReachable(timeOut)”。因为您的程序可能会多次尝试连接到该 IP。
  • 尝试在将套接字绑定到地址之前添加clientSocket.setReuseAddress(true);(在SO上的许多类似问题中建议)
  • @jayeshsolanki93 我的主帖里已经有这行了

标签: java android sockets tcp


【解决方案1】:

我真的不明白为什么有时我会收到此异常

您要绑定的端口已在使用中。

我在这里看到几篇帖子建议在绑定套接字上做一个循环,但我认为它应该执行一次,并且在其他地方有问题。

我同意。问题是其他一些进程已经在使用该端口。例如,可能是对您的应用程序的先前调用。确保它已退出。如果不是这样,您将不得不找到它是什么进程并采取任何适当的补救措施,或者使用不同的端口号。

我看到您已经在使用 setReuseAddress(true),它解决了最常见的情况。

也许与清理线程套接字资源有关?

没有。

【讨论】:

  • 为了清楚起见,setReuseAddress(true) 将在使用同一端口的连接处于 TIME_WAIT 状态时很有用,但如果它仍然处于活动状态,这将无济于事
  • 那么您有什么建议,当出现此问题时,我可以清除应用程序当前正在使用的所有端口吗?
  • 也许我需要使用 Executors.newFixedThreadPool 来处理服务器发送的每个请求?
  • @visionixvisionix 我的建议包含在我的回答中,它不包含任何关于“清除 [ing] 应用程序当前正在使用的所有端口”的内容。如果应用程序试图将新的ServerSocket 绑定到它已经在使用的端口,则它存在严重错误,应该在编译之前进行整理。摆弄线程池并不能解决这个问题。
  • 我不太明白什么时候会出现这种情况,会不会是路由器的问题?
猜你喜欢
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-13
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多