让JRTPLIB 发送/接收数据时使用同一个端口

这两周在做MPEG4视频传输时,想借助STUN协议穿透内网实现P2P,但是却发现 JRTPLIB在发送数据和 接收数据时使用的不是同一个PORT,这就可能导致无法穿透内网,我的想法大致如下:

假设A的RTP使用端口1000,则起对应的RTCP端口必定为1001,在初始化RTP信令后,JRTPLIB会随机使用另外一个端口3333来发送RTP数据,1000端口是用来接收RTP数据的,1001接收RTCP包。

假设B的RTP使用端口2000,则起对应的RTCP端口必定为2001,在初始化RTP信令后,JRTPLIB会随机使用另外一个端口4444来发送RTP数据,2000端口是用来接收RTP数据的,2001接收RTCP包。

又假设A,B均在NAT后,经NAT转换后,利用STUN协议,A开始向B发包,B也向A发包,由于NAT的存在,B发给A的包并不是A发出去的目的地址端口发过来的,目的端口只受数据不发数据(A将数据包发给B的RTP接收端口后,NAT A就只接收B的这个RTP端口发过来的数据,对于B用来发送数据的端口而言,是不请自到的),因此NAT A会丢弃B发过来的包,同理NAT B也会丢弃A发过来的包。

这样一来,为了能UDP PUNCH HOLE,A,B就必须再往对方用来发送数据的端口打一个洞,以便欺骗NAT,但UDP是不可靠的,而NAT影射也有时间限制,要保证NAT的影射关系不变就的定时打洞给对方,个人感觉这种方法不是很好。

经过查看JRTPLIB源码,它的Create()函数里是这么写的

addr.sin_family = AF_INET;
addr.sin_port = htons(0); //就是这里使用随机端口
addr.sin_addr.s_addr = htonl(0);
if (bind(sendsock,(struct sockaddr *)&addr,sizeof(struct sockaddr)) != 0)
{
return ERR_RTP_CANTBINDSOCKET;
}

socklen = sizeof(struct sockaddr_in);
if (getsockname(sendsock,(struct sockaddr *)&addr,&socklen) != 0)
{
return ERR_RTP_CANTGETSOCKETPORT;
}
sendport = ntohs(addr.sin_port);//这里是发送数据的端口

很明显,它用的是随机端口,BIND成功后再查询这个端口的,在RTPSession里用于获取发送端口的函数GetSendPort()直接返回了这个sendport,如下:

int GetSendPort()
{
return sendport;
}

为此,我只好修改JRTPLIB V2.9的源码了,在rtpconnection.cpp里,将发送数据的sendto语句里的socket都换成rtpsocket,让他使用bind在rtp端口的socket即可,同时删除sendsocket,并将GetSendPort()直接返回portbase。经过修改,发送/接收数据时就只有RTP和RTCP端口了,而且收发数据都通过RTP绑定的那个端口进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值