从一侧调用时在JMF中建立双工RTD连接,但在从另一侧调用时无法访问端口

时间:2014-03-26 11:53:15

标签: rtp jmf jain-sip rtcp

我使用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中,目标端口无法访问。请建议这个问题的解决方案是什么以及为什么会出现这个问题。

1 个答案:

答案 0 :(得分:1)

无论如何我已经解决了这个问题,我认为这对许多人来说都是一个问题,所以请不要删除它。原因' Port Unreachable'来得很简单:您分配的端口可能已被使用,或者您可能忽略了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");
    }
相关问题