Как повторно использовать DatagramSocket? - PullRequest
1 голос
/ 17 января 2012

У меня проблема с использованием DatagramSocket. Проблема в том, что я не могу запустить два теста Android JUnit один за другим, используя DatagramSockets, потому что второй тест выдает следующее исключение:

java.net.BindException: Address already in use

Я полагаю, что это будет проблемой и для Активностей, потому что, когда Активность перемещается с фона на передний план, я, вероятно, получаю те же исключения.

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

    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 ]

3 голосов
/ 18 января 2012

хорошо, я просто некоторое время смотрел на твой код и понял, что ты никогда не звонишь:

serverSocket.close();

звоните после звонка:

serverSocket.disconnect();

и ваша проблема должна быть решена.

0 голосов
/ 17 января 2012

Ваш код:

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

Будет закорочено, если экземпляр serverSocket равен нулю, иначе вторая проверка, чтобы убедиться, что он не связан, может не быть вызвана.

Имейте также в виду, что между вызовом disconnect вашего сокета дейтаграммы и моментом, когда операционная система действительно освобождает указанный сокет для повторного использования, может быть период задержки.

...