Метод getSocketAddress () вызывает задержку, которая приводит к задержке связи в Android - PullRequest
1 голос
/ 27 января 2012

Я разрабатываю ответчик UDP для обработки основных команд SSDP.Целью этого фрагмента кода является автоматическое обнаружение, поэтому, когда сервер отправляет многоадресную рассылку в определенную группу, все остальные подписанные устройства должны отправлять обратно пакет UDP, сообщая о своем присутствии хосту и порту отправителя многоадресной рассылки.Мое устройство Android получает и отправляет пакет просто отлично, но из-за того, что для возврата объекта SocketAddress из метода getSocketAddress () у сервера слишком много времени, сервер закрывает порт прослушивания и никогда не получает пакет обратно с устройства Android.

Вот мой код:

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    MulticastSocket ms = null;
    byte[] packBuf = new byte[128];
    try {
        ms = new MulticastSocket(32410);
        ms.joinGroup(InetAddress.getByName("239.255.255.250"));
    } catch (IOException e3) {
        // TODO Auto-generated catch block
        e3.printStackTrace();
    }

    while (true)
    {
        DatagramPacket receivedPack = new DatagramPacket(packBuf, packBuf.length);
        try {
            ms.receive(receivedPack);
            Log.d(TAG, "Received data");

        } catch (IOException e3) {
            // TODO Auto-generated catch block
            e3.printStackTrace();
        }

        String responseStr = "HTTP/1.0 200 OK\n" + 
           "Content-Type: app\n" + 
           "Resource-Identifier: 945e7dd5913ab45f1db4f271a1620b9471fb7d4d\n" +
           "Name: Test App\n" +
           "Port: 8888\n" + 
           "Updated-At: 1319511680\n" +
           "Version: 0.9.3.4-29679ad\n" +
           "Content-Length: 23\n\n" + 
           "<message>test</message>";

        byte[] response = responseStr.getBytes();

        DatagramSocket sendSocket = null;
        try {
            sendSocket = new DatagramSocket();

        } catch (IOException e2) {
            // TODO Auto-generated catch block
            Log.e(TAG,"Erro",e2);
        }

        DatagramPacket outPack;
        try {
            outPack = new DatagramPacket(response, responseStr.length(), receivedPack.getSocketAddress());
            sendSocket.send(outPack);
        } catch (UnknownHostException e1) {
            Log.e(TAG,"Erro",e1);
        }
        catch (IOException e) {
            Log.e(TAG,"Erro",e);
        }
        catch (Exception e)
        {
            Log.e(TAG,"Erro",e);
        }
    }
}

Есть идеи?

спасибо заранее,

fbr

Ответы [ 2 ]

1 голос
/ 31 января 2012

Наиболее вероятная проблема заключается в том, что getSocketAddress() пытается разрешить DNS-имя IP-адреса, время которого истекает либо из-за многоадресного адреса, либо из-за общей задержки DNS.

The *Класс 1004 * имеет опцию конструктора needResolved, которая может управлять этим поведением.К сожалению, не похоже, что DatagramPacket.getSocketAddress() позволяет вам указать, что вы хотите установить значение false.

Это, очевидно, известная проблема, с недавним обсуждением ее здесь: Проблема 12328: DatagramChannel- не может получить без поиска имени хоста

Поток предполагает, что это было исправлено в Android 3.0, и предлагает несколько обходных путей для Android 2.0, которые могут работать или не работать.

В вашем случае вы можете попробовать создать InetSocketAddress с INADDR_ANY и портом 0 с needsResolved, установленным на 0, а затем передать его при создании receivedPack.Надеюсь, receive() будет использовать его повторно и запомнит настройки.

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

2 вещи приходят на ум ...

1) Что происходит, когда вы меняете:

outPack = new DatagramPacket(response, responseStr.length(), receivedPack.getSocketAddress());

до

outPack = new DatagramPacket(response, responseStr.length(), receivedPack.getAddress(), receivedPack.getPort());

2) Я помню такую ​​проблему со встроенной Java в системе домашней автоматизации. Нашим краткосрочным решением было поместить большую часть машинных и многоадресных адресов в файл hosts. В долгосрочной перспективе мы получили локальный DNS-сервер.

Где-то в сетевом стеке Java есть параметр, который указывает, как долго кэшировать сбои DNS в памяти. Я думаю, мы набрали это число до 5 минут вместо 10 секунд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...