2016-05-22 3 views
0

Осмотрев несколько сообщений об этой ошибке, я не очень понимаю, почему иногда я получаю это исключениесокет TCP IOExceptionbind не удался: EADDRINUSE (адрес уже используется)

Я видел несколько сообщений здесь, что предложило сделать цикл за привязку сокета, но я думаю, что он должен быть выполнен один раз и есть проблема где-то в другом месте.

Это мой код:

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

Может быть что-то делать с чисткой нить сокеты ресурсы?

+0

, кажется, что номер порта или IP-адрес, который вы попробуйте использовать занят! – pooyan

+0

и что мне нужно делать, если он занят? Мне нужно получить обратную связь с сервером, могу ли я заставить его закрыть? –

+0

Я не уверен, если это возможно. но сначала убедитесь, что ваш ip занят. для этого с помощью кода попробуйте «InetAddress.getByName (host) .isReachable (timeOut)». потому что возможно, что ваша программа сама пытается подключиться к этому ip более одного раза. – pooyan

ответ

1

Я не очень понимаю, почему иногда я получаю это исключение

порт вы привязки к уже используется.

Я видел несколько сообщений здесь, которые предложили сделать цикл, привязав к сокету, но я думаю, что он должен быть выполнен один раз и есть проблема где-то в другом месте.

Согласен. Проблема в том, что какой-то другой процесс уже использует порт. Возможно, например, предыдущий вызов вашего приложения. Убедитесь, что он вышел. Если это не так, вам придется либо найти, что это за процесс, либо принять любое исправление, или использовать другой номер порта.

Я вижу, вы уже используете setReuseAddress(true), который решает наиболее распространенный случай этого.

Возможно, что-то связано с очисткой ресурсов сокетов резьбы?

No.

+0

, просто чтобы понять, 'setReuseAddress (true)' будет полезна, если соединение с использованием того же порта находится в состоянии 'TIME_WAIT', но в случае, если оно все еще активно, это ничего не сделает. – Yazan

+0

Итак, что вы предлагаете, могу ли я очистить все порты, которые приложение использует в настоящее время при возникновении этой проблемы? –

+0

Возможно, мне нужно использовать Executors.newFixedThreadPool для работы над каждым из моих запросов, которые были отправлены сервером? –