如何重用DatagramSocket?

时间:2012-01-17 18:23:01

标签: java android sockets bind unbind

我使用DatagramSocket时遇到问题。问题是我无法使用DatagramSockets一个接一个地运行两个Android JUnit测试,因为第二个测试会引发以下异常:

java.net.BindException: Address already in use

我想这也是活动中的一个问题,因为当Activity从后台移动到前台时,我可能会得到相同的例外。

我很满意,如果我可以断开连接并重新连接套接字,或者如果我能够重用旧套接字但我无法让其中一个工作。我的重用概念看起来像这样:

    if (serverSocket == null || !serverSocket.isBound())  {
        serverSocket = new DatagramSocket(9800);
    }

但这不起作用,同样的例外。当我尝试重新实现它时,它甚至不起作用(当我不否定第二个术语时)。

我试图解除并重新连接......

        serverSocket.disconnect();
        serverSocket = new DatagramSocket(null); 
        serverSocket.setReuseAddress(true);
        serverSocket.bind(new InetSocketAddress("localhost", 9800));

也不起作用。执行第二次测试时出现相同的异常。我该怎么做才能解决这个问题?这是全班:

public class UdpListener extends Thread implements Subject {
    private DatagramSocket serverSocket;
    private DatagramPacket receivedPacket;
    private volatile boolean running = false;
    private String sentence = "";

    private Observer observer;

    private static final String TAG = "UdpListener";

    public UdpListener(Observer o) throws SocketException  {
        observer = o;

        if (serverSocket == null || !serverSocket.isBound())  {
            serverSocket = new DatagramSocket(9800);
        }
    }

    @Override
    public void run() {
        setName(TAG);
        while (isRunning())  {
            byte[] receivedData = new byte[1024];
            receivedPacket = new DatagramPacket(receivedData, receivedData.length);
            try {
                serverSocket.receive(receivedPacket);
            } 
            catch (IOException e) {
                Log.w(TAG, e.getMessage());
            }

            try {
                sentence = new String(receivedPacket.getData(), 0, receivedPacket.getLength(), "UTF-8");
                if (UdpState.UPDATE.toString().equals(sentence))  {
                    notifyObserver();
                }
            } 
            catch (UnsupportedEncodingException e) {
                Log.w(TAG, e.getMessage());
            }
        }
    }

    private boolean isRunning() {
        return running;
    }

    public void setThreadRunning(boolean running) throws SocketException {
        this.running = running;
        if (running)  {
//          serverSocket = new DatagramSocket(9800);
            this.start();
        }
        else  {
//          serverSocket.disconnect();
//          serverSocket = new DatagramSocket(null); 
//          serverSocket.setReuseAddress(true);
//          serverSocket.bind(new InetSocketAddress("localhost", 9800));
        }
    }

    @Override
    public void notifyObserver() {
        observer.update();
    }
}

2 个答案:

答案 0 :(得分:3)

好吧我只是看了你的代码一段时间,我才意识到你从不打电话:

serverSocket.close();

致电后致电:

serverSocket.disconnect();

你的问题应该解决了。

答案 1 :(得分:0)

您的代码:

if (serverSocket == null || !serverSocket.isBound())  {
    serverSocket = new DatagramSocket(9800);
}

如果serverSocket实例为空,则会被短路,也就是第二次检查以确保它不被绑定可能不会被调用。

请记住,在数据报套接字上调用disconnect与操作系统实际释放所述套接字以供重用之间可能存在延迟时间。