Дуплексное соединение RTP устанавливается в JMF при вызове с одной стороны, но становится недоступным порт при вызове с другой стороны

Я использовал JMF для передачи и получения звука для приложения, использующего JAIN-SIP, и ниже приведен мой код:

import com.sun.media.rtp.RTPSessionMgr;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.*;
import javax.media.format.AudioFormat;
import javax.media.format.UnsupportedFormatException;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.rtp.InvalidSessionAddressException;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.SendStream;
import javax.media.rtp.SessionAddress;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
 import java.net.*;
import javax.media.control.TrackControl;
 import javax.media.rtp.*;
import com.sun.media.rtp.*;
import javax.media.rtp.RTPManager;



/**
*
* @author dexter
*/
public class Transmitter extends Thread implements ReceiveStreamListener  {

   static Processor mp;
   static DataSink ds;
     String ip,port;
     RTPManager rtp;
     SendStream ss;
     ReceiveStream rs;
     DataSource rds,ods,source;
      Player player;
      SessionAddress remoteaddr;

   public void run()
   {
       try {
           Format[] formats= new Format[]{new AudioFormat(AudioFormat.ULAW_RTP)};

           ContentDescriptor cd= new ContentDescriptor(ContentDescriptor.RAW_RTP);

           Vector devices= CaptureDeviceManager.getDeviceList(new
AudioFormat("linear",8000,16,2));
            System.out.println("devices="+devices);


           CaptureDeviceInfo di=(CaptureDeviceInfo) devices.firstElement();
System.out.println("device info="+di);

           MediaLocator ml= di.getLocator();
System.out.println("locator="+ml);

try {
                source = javax.media.Manager.createDataSource(ml);
            }
            catch (Exception e) {
                // Try JavaSound Locator as a last resort
                try {
                    source= javax.media.Manager.createDataSource(new MediaLocator("javasound://"));
                }
                catch (Exception ee) {
                    System.err.println("Couldn't create DataSource");
                }
            }

           mp=Manager.createRealizedProcessor(new ProcessorModel(source,formats,cd));

           mp.start();

          rtp=RTPManager.newInstance();
         // rtp.addReceiveStreamListener((ReceiveStreamListener) this);
       SessionAddress localaddr= new SessionAddress(InetAddress.getByName(Phone.ip),Integer.parseInt(SipLayer.caller_port));
           remoteaddr= new SessionAddress(InetAddress.getByName(ip),new Integer(port));

          rtp.initialize(localaddr);
          rtp.addReceiveStreamListener(this);

         rtp.addTarget(remoteaddr);


          ss=rtp.createSendStream(mp.getDataOutput(),0);

     //     mp.start();
          ss.start();

       } catch (UnsupportedFormatException ex) {
            Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidSessionAddressException ex) {
            Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
        }  catch (CannotRealizeException ex) {
            Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
        }  catch (IOException ex) {
           Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
       } catch (NoProcessorException ex) {
           Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
       } 
   }

   public  Transmitter(String callee_ip,String callee_port)
{
    ip=callee_ip;
    port= callee_port;
}

    public void update(ReceiveStreamEvent rse) {

        if(rse instanceof NewReceiveStreamEvent)
        {
            try {
                 rs = rse.getReceiveStream();
                rds = rs.getDataSource();
                player = Manager.createPlayer(rds);
                player.start();
            } catch (IOException ex) {
                Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoPlayerException ex) {
                Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    public void stop_media()
    {
        try{
            player.stop();
            player.deallocate();
            player.close();
            ss.stop();
          // necessary for sending rtcp bye
            mp.stop();
            mp.close();
            mp.deallocate();
            ss.close();
         //   
            rtp.removeTarget(remoteaddr," disconnected");
            rtp.dispose();
        }catch(Exception e){

        }
    }
}

Проблема в том, что когда я создаю соединение из своего приложения (т.е. звоню), проблем нет, и я могу отправлять и получать аудио. Но когда мне звонят, я слышу другую сторону, а другая меня не слышит. В wireshark порт назначения недоступен. Пожалуйста, подскажите, как решить эту проблему и почему она возникает.


person Manish    schedule 26.03.2014    source источник


Ответы (1)


В любом случае, я решил вопрос, и я думаю, что это было проблемой для многих, поэтому, пожалуйста, не удаляйте его. Причина, по которой появляется сообщение «Порт недоступен», проста: выделенный вами порт мог быть использован или вы, возможно, проигнорировали тот факт, что RTP требует порт с четным номером для отправки данных и порт с нечетным номером для RTCP. И RTCP обрабатывается JMF автоматически. Просто найдите неиспользуемый порт UDP с четным номером и используйте его для отправки RTP. Кроме того, отключите брандмауэр, если не удается получить какой-либо пакет (SIP или RTP).

public static int findFreePort() {
        DatagramSocket socket = null;
                int port=1;
        try {
                    while(port%2!=0)
                    {
                        socket = new DatagramSocket(0);

            socket.setReuseAddress(true);
             port = socket.getLocalPort();
                         socket.close();
                    }   
            return port;
        } catch (IOException e) { 
        } finally {
            if (socket != null) {
                            socket.close();
            }
        }
        throw new IllegalStateException("Could not find a free UDP port to start");
    }
person Manish    schedule 03.04.2014