前几篇文章讲了使用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,黑客搞远程控制必备技能啊)。
具体到代码中的话,如下:
- 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();
这个里面没做读写检查,不过无所谓了,已经能用了
参考文档:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!