Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31039980
  • 博文数量: 230
  • 博客积分: 2868
  • 博客等级: 少校
  • 技术积分: 2223
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-08 21:48
个人简介

Live & Learn

文章分类

全部博文(230)

文章存档

2022年(2)

2019年(5)

2018年(15)

2017年(42)

2016年(24)

2015年(13)

2014年(1)

2012年(5)

2011年(58)

2010年(56)

2009年(9)

我的朋友

分类: 其他平台

2017-09-22 10:24:35

前几篇文章讲了使用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 plain copy
  1. int rtpsock = ((RTPUDPv4TransmissionInfo *)m_pRTPSessionVideo->GetTransmissionInfo())->GetRTPSocket();  
  2.         if (rtpsock != -1) {  
  3.             sockaddr_in skAddr;  
  4.             unsigned long destAddr = inet_addr("112.20.30.40");  
  5.             memcpy(&skAddr.sin_addr, &destAddr, sizeof(destAddr));  
  6.             skAddr.sin_port = htons(18000);  
  7.             skAddr.sin_family = AF_INET;  
  8.   
  9.             status = connect(rtpsock, (sockaddr *)&skAddr, sizeof(skAddr));  
  10.             LOGI("status is %d", status);  
  11.             int sendcount = send(rtpsock, (void *)"test"sizeof("test"), 0);  
  12.             LOGI("rtpsock is %d, send data %d", rtpsock,sendcount);  
  13.         }  
  14.         m_pRTPSessionVideo->BeginDataAccess();  



这个里面没做读写检查,不过无所谓了,已经能用了


参考文档: 

jrtplib-2.9 校园NAT冲突解决

阅读(1562) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~