jrtplib跨网络通讯NAT穿透问题解决方法
2014-03-12 16:52
239 查看
前几篇文章讲了使用jrtplib在Android和pc端进行通讯的方法
在实际项目中,手机端和pc端一般不会在同一个子网内,两者之间联络可能要走路由器之类的NAT(网络地址转换 Network Address
Translation))设备
假设服务端IP地址为 112.20.30.40,管理多个摄像头
服务端建立一个serversocket绑定固定的端口如8000,用来接收客户端的请求
对于不同的摄像头分别建立不同的rtpsession,用来发送视频流到客户端,比如“camera1”对应的rtp端口为18000
当客户端请求此摄像头数据时,便将客户端的ip和rtp端口加到rtpsession的destination中(观察者模式),然后发送视频数据
客户端(IP假设为192.168.1.100), 建立rtp对象用来接收服务端发送的视频流,端口设置为9000,
客户端连接到的路由器IP地址为192.168.1.1,对应的外网地址为172.20.30.200,
但NAT的行为模式是,只能从内部开门,也就是说,服务端如果想通过18000端口往客户端的9000端口发数据的话
这个数据在路由器上就直接被抛弃掉了,不会转发到客户端,解决方法很简单,客户端在接收数据之前先往服务端的18000端口随便发个数据,
这样门就打开了,服务端的数据就可以进来了(专业一点的术语叫UDP hole punching,黑客搞远程控制必备技能啊)。
具体到代码中的话,如下:
[cpp]
view plaincopyprint?
int rtpsock = ((RTPUDPv4TransmissionInfo *)m_pRTPSessionVideo->GetTransmissionInfo())->GetRTPSocket();
if (rtpsock != -1) {
sockaddr_in skAddr;
unsigned long destAddr = inet_addr("112.20.30.40");
memcpy(&skAddr.sin_addr, &destAddr, sizeof(destAddr));
skAddr.sin_port = htons(18000);
skAddr.sin_family = AF_INET;
status = connect(rtpsock, (sockaddr *)&skAddr, sizeof(skAddr));
LOGI("status is %d", status);
int sendcount = send(rtpsock, (void *)"test", sizeof("test"), 0);
LOGI("rtpsock is %d, send data %d", rtpsock,sendcount);
}
m_pRTPSessionVideo->BeginDataAccess();
这个里面没做读写检查,不过无所谓了,已经能用了
参考文档:
在实际项目中,手机端和pc端一般不会在同一个子网内,两者之间联络可能要走路由器之类的NAT(网络地址转换 Network Address
Translation))设备
假设服务端IP地址为 112.20.30.40,管理多个摄像头
服务端建立一个serversocket绑定固定的端口如8000,用来接收客户端的请求
对于不同的摄像头分别建立不同的rtpsession,用来发送视频流到客户端,比如“camera1”对应的rtp端口为18000
当客户端请求此摄像头数据时,便将客户端的ip和rtp端口加到rtpsession的destination中(观察者模式),然后发送视频数据
客户端(IP假设为192.168.1.100), 建立rtp对象用来接收服务端发送的视频流,端口设置为9000,
客户端连接到的路由器IP地址为192.168.1.1,对应的外网地址为172.20.30.200,
但NAT的行为模式是,只能从内部开门,也就是说,服务端如果想通过18000端口往客户端的9000端口发数据的话
这个数据在路由器上就直接被抛弃掉了,不会转发到客户端,解决方法很简单,客户端在接收数据之前先往服务端的18000端口随便发个数据,
这样门就打开了,服务端的数据就可以进来了(专业一点的术语叫UDP hole punching,黑客搞远程控制必备技能啊)。
具体到代码中的话,如下:
[cpp]
view plaincopyprint?
int rtpsock = ((RTPUDPv4TransmissionInfo *)m_pRTPSessionVideo->GetTransmissionInfo())->GetRTPSocket();
if (rtpsock != -1) {
sockaddr_in skAddr;
unsigned long destAddr = inet_addr("112.20.30.40");
memcpy(&skAddr.sin_addr, &destAddr, sizeof(destAddr));
skAddr.sin_port = htons(18000);
skAddr.sin_family = AF_INET;
status = connect(rtpsock, (sockaddr *)&skAddr, sizeof(skAddr));
LOGI("status is %d", status);
int sendcount = send(rtpsock, (void *)"test", sizeof("test"), 0);
LOGI("rtpsock is %d, send data %d", rtpsock,sendcount);
}
m_pRTPSessionVideo->BeginDataAccess();
int rtpsock = ((RTPUDPv4TransmissionInfo *)m_pRTPSessionVideo->GetTransmissionInfo())->GetRTPSocket(); if (rtpsock != -1) { sockaddr_in skAddr; unsigned long destAddr = inet_addr("112.20.30.40"); memcpy(&skAddr.sin_addr, &destAddr, sizeof(destAddr)); skAddr.sin_port = htons(18000); skAddr.sin_family = AF_INET; status = connect(rtpsock, (sockaddr *)&skAddr, sizeof(skAddr)); LOGI("status is %d", status); int sendcount = send(rtpsock, (void *)"test", sizeof("test"), 0); LOGI("rtpsock is %d, send data %d", rtpsock,sendcount); } m_pRTPSessionVideo->BeginDataAccess();
这个里面没做读写检查,不过无所谓了,已经能用了
参考文档:
jrtplib-2.9 校园NAT冲突解决
链接:http://blog.csdn.net/nickwar/article/details/9133399
相关文章推荐
- jrtplib跨网络通讯NAT穿透问题解决方法
- jrtplib跨网络通讯NAT穿透问题解决方法
- jrtplib跨网络通讯NAT穿透问题解决方法
- JRTPLIB编译说出现的问题及解决方法(转载)
- JRTPLIB编译说出现的问题及解决方法(转载)
- “无任何网络提供程序接受指定的网络路径”问题的几个解决方法
- 在Win下搭建CentOS 6网络安装源时/repodata目录下文件名后缀丢失问题及解决方法
- windows使用libvlc进行网络串流遇到的一些问题及解决方法
- socket iOS 与java 后台进行socket通讯遇到的问题以及解决方法
- window Server 2008中因防火墙规则有些软件不能在PC间通讯问题的解决方法
- eclipse 使用git碰到网络超时连接不了等问题的解决方法
- 安卓4.0以后主线程访问网络问题(NetworkOnMainThreadException)解决方法及子线程更新ui
- 网络打印机打印超慢或者打印不出的问题解决方法
- SAMBA配置 “你可能没有权限访问网络资源”的问题解决方法
- Android中利用NetworkInfo判断网络状态时出现空指针(NullPointerException)问题的解决方法
- socket iOS 与java 后台进行socket通讯遇到的问题以及解决方法
- windows无法配置此无线连接的无线网络问题解决方法
- Android 异步获取网络图片并处理导致内存溢出问题解决方法
- window Server 2008中因防火墙规则有些软件不能在PC间通讯问题的解决方法
- “无任何网络提供程序接受指定的网络路径”问题的几个解决方法