插座未正确关闭

时间:2010-06-25 21:30:27

标签: java sockets udp datagram

我正在尝试创建一个将在单独的线程上侦听的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已进入同步块!!!   java.net.SocketException:无法识别的Windows套接字错误:0:无法绑定       at java.net.PlainDatagramSocketImpl.bind0(Native Method)       在java.net.PlainDatagramSocketImpl.bind(未知来源)

指向sock.recieve(pack)的行; 看起来由于某种原因,套接字没有关闭,因为,我认为,它在sock.recieve(pack)等待,并且永远不会离开while循环来关闭套接字。我怎么会绕过这个呢?

由于

2 个答案:

答案 0 :(得分:2)

正如Peter Tillemans所说,你应该设置一个接收超时,这样你就不会坐在那里试图永远接收()。

另外,保持new Thread(listenerRunnable)返回的Thread对象,以便stopListening()方法可以等待线程死掉:

public void stopListening() {
    keepListening = false;
    listenerThread.join();
}

答案 1 :(得分:1)

在调用receive之前,您必须添加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();
        }