0

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

4

1 回答 1

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");
    }
于 2014-04-03T11:04:13.690 回答