2013-11-26 3 views
0

У меня есть библиотека, которую мне нужно улучшить, поскольку она отбрасывается во многие пакеты. Я хочу получить RTP-Stream, но стример отправляет пакеты из 30-40 пакетов в миллисекунду (MJPEG-Stream). Я вижу, что пакеты завершаются при мониторинге трафика в Wireshark. Но, пытаясь получить их на Java, я теряю много этих пакетов.Получение UDP в Java без отбрасывания пакетов

Я уже смог улучшить поведение библиотек, внедряя кольцевой буфер, который будет постоянно заполняться всякий раз, когда доступен пакет, и отдельный поток чтения, который читается из этого буфера. Но я все еще не могу получить все пакеты из своего сокета, которые я могу видеть в wirehark. Через номера последовательности RTP я могу отслеживать поток чтения, если обработанный пакет является ожидаемым.

Следующий код обрабатывает пакет получающее:

private volatile byte[][] packetBuffer = new byte[1500][BUFFER_SIZE]; 
private volatile DatagramPacket[] packets = new DatagramPacket[BUFFER_SIZE]; 
private volatile int writePointer = 0; 

public void run() { 
    Thread reader = new RTPReaderThread(); 
    reader.start(); 

    while (!rtpSession.endSession) { 

     // Prepare a packet 
     packetBuffer[writePointer] = new byte[1500]; 
     DatagramPacket packet = new DatagramPacket(packetBuffer[writePointer], packetBuffer[writePointer].length); 

     // Wait for it to arrive 
     if (!rtpSession.mcSession) { 
      // Unicast 
      try { 
       rtpSession.rtpSock.receive(packet); 
      } catch (IOException e) { 
       if (!rtpSession.endSession) { 
        e.printStackTrace(); 
       } else { 
        continue; 
       } 
      } 
     } else { 
      // Multicast 
      try { 
       rtpSession.rtpMCSock.receive(packet); 
      } catch (IOException e) { 
       if (!rtpSession.endSession) { 
        e.printStackTrace(); 
       } else { 
        continue; 
       } 
      } 
     } 
     packets[writePointer] = packet; 

     this.incrementWritePointer();   
     synchronized (reader) { 
      reader.notify(); 
     } 
    } 
} 

То, что я уже знаю:

  • Я знаю, что UDP разрешено терять пакеты, но я все равно хочу достичь наилучшего результат. Если wirehark может видеть пакет, я хочу, чтобы его можно было получить, если это возможно.
  • Я знаю, что кольцевой буфер никогда не заполняется при потере пакетов, поэтому это не заставляет меня потерять пакеты. Я попытался с BUFFER_SIZES из 100 и даже 1000, но я уже потерял первые пакеты до того, как было отправлено всего 1000 пакетов.

Итак, вопрос в том, что лучше всего принимать как можно больше пакетов из DatagramSocket? Могу ли я улучшить обработку пакетов пакетов?

ответ

2

Попробуйте установить размер SO_RCVBUF на гнездо дейтаграммы с помощью rtpSock.setReceiveBufferSize(size). Это только предположение для ОС, и ОС не может почитать ее, особенно если она слишком велика. Но я бы попытался установить его (SIZE_OF_PACKET * 30 * 100), где 30 - количество пакетов в пакете, а 100 - количество миллисекунд, где вы не сможете идти в ногу со скоростью прибытия ,

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

+0

Большое спасибо, я попробую это. Я не беспокоюсь о скорости поиска, это просто, что некоторые пакеты иногда уже ушли к тому времени, когда цикл пытается их получить. – noamik

+0

Хорошо, это именно то, что я искал. Большое спасибо за вашу помощь. – noamik

+0

Еще одно замечание, а не использование '' synchronize'' и '' notify() '', создайте '' java.util.concurrent.LinkedTransferQueue'', а в принимающем потоке выполните '' transfer() ' 'поставить пакет в очередь, в то время как поток обработки выполняет' 'take()' 'из одной очереди. Это будет намного более результативным, чем синхронизация/уведомление. – brettw

Смежные вопросы