2010-06-25 2 views
2

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

listenerRunnable = new Runnable() { 
     public void run() { 
      //This thread will listen keep listening to the UDP traffic and put it to the log source string 
      try { 
       sock = new DatagramSocket(portNumber); 
      } catch (SocketException e1) { 
       // TODO Auto-generated catch block 
       e1.printStackTrace(); 
      } 
      while(keepListening) { 
       try { 
        pack = new DatagramPacket(recievedData, BUFFERSIZE); 
        sock.receive(pack); 

        String data = new String(pack.getData(), 0, pack.getLength()); 
        addToLog(data); 
        System.out.println(data); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       sock.close(); 
      } 
     } 
    }; 

/** 
* Function to start the listening thread. 
*/ 
public void startListening(int portNum) { 
    keepListening = true; 
    portNumber = portNum; 

    listenerThread = new Thread(listenerRunnable); 

    logSource_buffer = ""; 
    logSourcehtml_buffer = ""; 
    logSourcehtml_temp = ""; 
    ipListIndex_beg = 0; 
    ipListIndex_end = -1; 

    if(!listenerThread.isAlive()) { 
     listenerThread.start(); 
    } 
} 

/** 
* stops the listening thead. When the listening thread sees that keepListening is set to false 
* it will reach the end of its loop, close the socket, and the thread will die. 
*/ 
public void stopListening() { 
    keepListening = false; 
} 

Это дает мне следующую ошибку:

logUpdatingThread has entered synchronized block!!! java.net.SocketException: Unrecognized Windows Sockets error: 0: Cannot bind at java.net.PlainDatagramSocketImpl.bind0(Native Method) at java.net.PlainDatagramSocketImpl.bind(Unknown Source)

, который указывает на строку с sock.recieve (пакет); Кажется, что по какой-то причине сокет не закрывается, потому что, я думаю, его ждет на sock.recieve (pack) и никогда не выходит из цикла while, чтобы закрыть сокет. Как мне обойти это?

Благодаря

ответ

1

Вы должны добавить setSoTimeout (тайм-аут) перед вызовом получить. Это будет регулярно вызывать SocketTimeoutExceptions, но не открывать сокет Datagram. Это позволит вам регулярно проверять переменную цикла.

Кроме того, вы должны переместить цикл внутри первого блока try-catch и добавить блок finally для закрытия сокета.

нравится:

 try { 
      sock = new DatagramSocket(portNumber); 
      sock.setSoTimeout(250); 
      while(keepListening) { 
       try { 
        pack = new DatagramPacket(recievedData, BUFFERSIZE); 
        sock.receive(pack); 

        String data = new String(pack.getData(), 0, pack.getLength()); 
        addToLog(data); 
        System.out.println(data); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } catch (SocketException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } finally { 
      sock.close(); 
     } 
2

Как сказал Питер Тилманс, вы должны установить получить тайм-аут, так что вы не сидите там пытаются получить() навсегда.

Кроме того, держать объект Thread возвращенного new Thread(listenerRunnable) так, что ваш метод stopListening() может ждать поток, чтобы умереть:

public void stopListening() { 
    keepListening = false; 
    listenerThread.join(); 
} 
Смежные вопросы