HOME> 葡萄牙世界杯冠军> 请教:怎么释放一次RTP会话(RTP session)中的端口

请教:怎么释放一次RTP会话(RTP session)中的端口

2025-05-30 15:25:36

社区

Java EE 帖子详情 请教:怎么释放一次RTP会话(RTP session)中的端口 shunshine988 2010-06-14 09:21:19 下面是基于JMF的一个媒体流发送类。有个问题:为什么调用一次这个类建立一次RTP session并发送完一个媒体流(如一个视频)后,(打印结果如一),再用同样的本地发送端口localPort就不能再发送了(打印结果如二),换成其他端口号后就可以了,我怀疑是上次RTP session的端口没有释放(相关语句为程序中标红的部分)。哪位高手帮忙看下是不是这个问题,怎么解决 或是怎么在一次媒体流发送完毕后释放掉占用的端口? 再此先谢过!

调用方法如下

RTPTransmit t=new RTPTransmit(filePath, localPort, destIP, destPort, beginMediaTime);

t.start();

打印下面语句为程序中标蓝的部分

一:

第一次可以发送媒体流时打印输出如下:

20:21:12,140 ERROR [STDERR] Track 0 is set to transmit as:

20:21:12,140 ERROR [STDERR] MPEG/RTP

20:21:12,140 ERROR [STDERR] Track 1 is set to transmit as:

20:21:12,140 ERROR [STDERR] mpegaudio/rtp, 44100.0 Hz, 16-bit, Stereo, LittleEndian, Signed, 8000.0 frame rate, FrameSize=32768 bits

20:21:12,156 ERROR [STDERR] Created RTP session: 192.168.100.107 6666 8000

20:21:12,171 ERROR [STDERR] Created RTP session: 192.168.100.107 6668 8002

二:

再用同样的本地发送端口发送时打印输出如下:

20:21:12,140 ERROR [STDERR] Track 0 is set to transmit as:

20:21:12,140 ERROR [STDERR] MPEG/RTP

20:21:12,140 ERROR [STDERR] Track 1 is set to transmit as:

20:21:12,140 ERROR [STDERR] mpegaudio/rtp, 44100.0 Hz, 16-bit, Stereo, LittleEndian, Signed, 8000.0 frame rate, FrameSize=32768 bits

即没有了Created RTP session: 192.168.100.107 6666 8000

Created RTP session: 192.168.100.107 6666 8002

public class RTPTransmit //用RTP协议传输数据的类

{

private MediaLocator locator;

private int localPort;

private String filePath;

private String destIP;

private int destPort;

private double beginMediaTime = 0.00;

private Processor processor = null;

private RTPManager rtpMgrs[];

private DataSource dataOutput = null;

public RTPTransmit(String filePath, int localPort, String destIP, int destPort, double beginMediaTime)

{

this.filePath = filePath;

this.localPort = localPort;

this.destIP = destIP;

this.destPort = destPort;

this.beginMediaTime = beginMediaTime;

}

public boolean setFilePath(String filepath)

{

if (filepath == "")

{

return false;

}

try

{

filepath = "file:/" + filepath;

this.locator = new MediaLocator(filepath);

}

catch (Exception e)

{

return false;

}

return true;

}

public synchronized String start()

{

this.setFilePath(this.filePath);

String result;

result = createProcessor();

if (result != null)

return result;

result = createTransmitter();

this.processor.setMediaTime(new Time(this.beginMediaTime));

if (result != null)

{

processor.close();

processor = null;

return result;

}

processor.start();

return null;

}

private String createProcessor() //为指定的媒体定位器产生一个处理器

{

if (locator == null)

return "Locator is null";

DataSource ds;

try

{

ds = javax.media.Manager.createDataSource(locator); //为定义的MediaLocator定位并 实例化一个适当的数据源

}

catch (Exception e)

{

return "Couldn't create DataSource";

}

try

{

processor = javax.media.Manager.createProcessor(ds); // 通过数据源产生一个处理器

}

catch (NoProcessorException npe)

{

return "Couldn't create processor";

}

catch (IOException ioe)

{

return "IOException creating processor";

}

boolean result = waitForState(processor, Processor.Configured); //等待处理器配置好

if (result == false)

return "Couldn't configure processor";

TrackControl[] tracks = processor.getTrackControls(); // 为媒体流中的每一个轨迹获取一个控制器

if (tracks == null || tracks.length < 1) // 确保至少有一个可用的轨迹

return "Couldn't find tracks in processor";

ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);

processor.setContentDescriptor(cd); //设置输出的内容描述为RAW_RTP

Track.getSupportedFormats()

Format supported[];

Format chosen = null;

boolean atLeastOneTrack = false;

for (int i = 0; i < tracks.length; i++)

{ //对于每一个轨迹

Format format = tracks[i].getFormat();

if (tracks[i].isEnabled())

{ //如果轨迹可用

supported = tracks[i].getSupportedFormats();

if (supported.length > 0)

{ //如果存在支持的格式

if (supported[0] instanceof VideoFormat)

{

chosen = checkForVideoSizes(tracks[i].getFormat(),

supported[0]); //检查视频格式的尺寸,以确保正常工作

}

else

chosen = supported[0]; // 选择第一种支持的格式即可

tracks[i].setFormat(chosen);

System.err.println("Track " + i + " is set to transmit as:");

System.err.println(" " + chosen); atLeastOneTrack = true;

}

else

tracks[i].setEnabled(false);

}

else

tracks[i].setEnabled(false);

}

if (!atLeastOneTrack) //如果每个轨迹都不存在合适的格式

return "Couldn't set any of the tracks to a valid RTP format";

result = waitForState(processor, Controller.Realized); // 等待处理器实现

if (result == false)

return "Couldn't realize processor";

dataOutput = processor.getDataOutput(); // 从处理器获取输出的数据源

return null;

}

private String createTransmitter() //产生RTP会话传输

{

PushBufferDataSource pbds = (PushBufferDataSource) dataOutput; // 将数据源转化成“Push”(推)数据源

PushBufferStream pbss[] = pbds.getStreams(); // 获取“Push”数据流

rtpMgrs = new RTPManager[pbss.length]; // 为每个轨迹产生一个RTP会话管理器

for (int i = 0; i < pbss.length; i++)

{

try

{

rtpMgrs[i] = RTPManager.newInstance();

int localport = this.localPort + 2 * i; //每增加一个轨迹,端口号加2

int destPort = this.destPort + 2 * i;

InetAddress ipAddr = InetAddress.getByName(this.destIP); //获取发送目的地的IP地址

SessionAddress localAddr = new SessionAddress(InetAddress

.getLocalHost(), localport); //获取本机的会话地址

SessionAddress destAddr = new SessionAddress(ipAddr, destPort);//获取目的机器(接收端)的会话地址

rtpMgrs[i].initialize(localAddr); //将本机会话地址传给RTP管理器

rtpMgrs[i].addTarget(destAddr); // 加入目的会话地址

System.err.println("Created RTP session: " + this.destIP + " "

+ destPort+" "localport);

SendStream sendStream = rtpMgrs[i].createSendStream(dataOutput,

i); // 产生数据源的RTP传输流

sendStream.start(); //开始RTP数据流传输

}

catch (Exception e)

{

return e.getMessage();

}

}

return null;

}

// 内部监听类:处理器的状态监听器

class StateListener implements ControllerListener

{

public void controllerUpdate(ControllerEvent ce)

{

if (ce instanceof ControllerClosedEvent) // 控制器关闭

setFailed();

if (ce instanceof ControllerEvent)

{ //对于所有的控制事件

synchronized (getStateLock())

{

getStateLock().notifyAll();

//通知在waitForState()方法中等待的线程

}

}

}

}

}

...全文

522 7 打赏 收藏 请教:怎么释放一次RTP会话(RTP session)中的端口 下面是基于JMF的一个媒体流发送类。有个问题:为什么调用一次这个类建立一次RTP session并发送完一个媒体流(如一个视频)后,(打印结果如一),再用同样的本地发送端口localPort就不能再发送了(打印结果如二),换成其他端口号后就可以了,我怀疑是上次RTP session的端口没有释放(相关语句为程序中标红的部分)。哪位高手帮忙看下是不是这个问题,怎么解决 或是怎么在一次媒体流发送完毕后释放掉占用的端口? 再此先谢过! 调用方法如下 RTPTransmit t=new RTPTrans 复制链接

扫一扫 分享 转发到动态 举报

写回复 配置赞助广告取 消

确 定

用AI写文章 7 条回复 切换为时间正序 请发表友善的回复… 发表回复 打赏红包 需支付: 0.00 元 取 消 确 定 injuer 2010-06-19 打赏举报 回复 RPT做媒体流的端口应该是独立的,换句话说应该P2P实现,不是理解为中转作用,域概念搞混了吧....

RPT需要自己实现CLIENT和SERVER,两者的端口应该独立. colin_pxx 2010-06-19 打赏举报 回复 这么长的代码看了就头晕 shunshine988 2010-06-19 打赏举报 回复 JMF的东西我也不怎么懂,现在老师让解决这个问题,都不知道怎么解决。为了能再次发送媒体流,只能是用新的端口再次发送了。

[Quote=引用 3 楼 injuer 的回复:]

RTP貌似不是调用方法就会释放端口了,第一次调用是侦测端口,第二次调用则是使用端口,如果第一次的方法未结束,会是第二次的发送被阻断,不想端口被占用,应该是对线程进行处理,而不是一直去想怎么释放SESSION,RPT的SESSION在线程之间是共享的.

[/Quote] zhanlang9075 2010-06-19 打赏举报 回复 I'm Sorry,小弟目前还没接触过JMF,只得帮顶一下。

[Quote=引用 3 楼 injuer 的回复:]

RTP貌似不是调用方法就会释放端口了,第一次调用是侦测端口,第二次调用则是使用端口,如果第一次的方法未结束,会是第二次的发送被阻断,不想端口被占用,应该是对线程进行处理,而不是一直去想怎么释放SESSION,RPT的SESSION在线程之间是共享的.

[/Quote]

学习了

injuer 2010-06-19 打赏举报 回复 RTP貌似不是调用方法就会释放端口了,第一次调用是侦测端口,第二次调用则是使用端口,如果第一次的方法未结束,会是第二次的发送被阻断,不想端口被占用,应该是对线程进行处理,而不是一直去想怎么释放SESSION,RPT的SESSION在线程之间是共享的. shunshine988 2010-06-18 打赏举报 回复 怎么没人理我啊,up shunshine988 2010-06-15 打赏举报 回复 有人懂JMF方面的东西吗,求助 rtp.rar_rtp_rtp session_rtp报文解析_rtp模块_丢包 在RTP报文解析中,每个RTP数据包由一个固定头部和可选的扩展头部以及负载数据组成。固定头部包含版本(Version)、填充位(Padding)、扩展位(Extension)、CSRC计数(CSRC Count)、标记位(Marker)、payload类型... rtp.zip_rtp_rtp 实现_rtp库 1. **初始化RTP会话**:创建一个新的RTP会话,设置必要的参数,如源和目的地的IP地址和端口,以及会话的媒体类型(音频或视频)。 2. **创建和发送RTP包**:构建RTP包头,包含序列号、时间戳、同步源标识符(SSRC)... RTP_javartp客户端_java_rtp_ 2. **创建RTP会话**:使用`RTPSession`类创建一个新的RTP会话,指定本地和远程的网络地址和端口。 3. **发送RTP数据**:通过`RTPSession`实例的`sendPacket()`方法发送RTP数据包,数据包通常包含编码后的音视频数据... RTP服务端如何调用 当RTP会话不再需要时,服务端需要正确地关闭会话,释放占用的资源,例如解绑端口、销毁RTPSession对象等。 在实际开发中,"RTP_Server"可能是一个包含示例代码、配置文件或工具的压缩包,帮助开发者更好地理解和... RTP协议实现H.264视频文件传输 4. RTP会话:RTP和RTCP一起定义了一个会话,同一会话中的所有参与者共享相同的SSRC。会话可以通过SDP(Session Description Protocol)来描述,包括媒体类型、传输地址、端口等信息。 5. RTP分片与重组:由于网络...

Java EE

67,550

社区成员

225,865

社区内容

发帖 与我相关 我的任务 Java EE J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。 复制链接

扫一扫 分享 确定 社区描述 J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。 社区管理员

加入社区

获取链接或二维码

近7日

近30日

至今

加载中

查看更多榜单

社区公告

暂无公告 试试用AI创作助手写篇文章吧

+ 用AI写文章

短裙英语(白色的短裙英语)

净水龙头·水龙头过滤器