RTP GB28181 udp 转发桥

目的

通往外网只有一个节点可以通,这个时候我们需要一个转发桥, 做一个udp 转发桥是非常简单的,简单而有用,我们使用asio c++ 来编程序

原理

使用asio 异步接收并且发送,在接收到以后,立刻在桥上转发,转发到外网地址。这里做演示,程序里面使用的是127.0.0.1.

代码

#define ASIO_STANDALONE
#include <iostream>
#include <cstdlib>
#include <iostream>
#include "asio.hpp"

using asio::ip::udp;
static const asio::ip::udp::endpoint s_end_point(asio::ip::address::from_string("127.0.0.1"), 6000);

class TicToc
{
public:
	TicToc()
	{
		tic();
	}

	void tic()
	{
		start = std::chrono::system_clock::now();
	}

	double toc()
	{
		end = std::chrono::system_clock::now();
		std::chrono::duration<double> elapsed_seconds = end - start;
		start = end;
		return elapsed_seconds.count() ;
	}

private:
	std::chrono::time_point<std::chrono::system_clock> start, end;
};

class server
{
private:
	TicToc v_tock;
public:
	server(asio::io_context& io_context, short port)
		: socket_(io_context, udp::endpoint(udp::v4(), port))
	{
		do_receive();
	}
	int64_t v_i = 0;
	uint64_t v_recvbytes = 0;
	void do_receive()
	{
		
		socket_.async_receive_from(
			asio::buffer(data_, max_length), sender_endpoint_,
			[this](std::error_code ec, std::size_t bytes_recvd)
		{
			if (!ec && bytes_recvd > 0)
			{
				if (v_i == 0)
					v_tock.tic();
				v_recvbytes += bytes_recvd;
				if (v_i++ > 100) //每一百个包统计一次
				{
					double res = v_tock.toc();
					float m = v_recvbytes / res /1000.0f;
					std::cout<<"time:"<<res<<" bytes:"<< v_recvbytes<<" recv byte every second:" << m <<"KB"<< std::endl;
					v_i = 0;
					v_recvbytes = 0;
				}
				do_send(bytes_recvd);
			}
			else
			{
				do_receive();
			}
		});
	}

	void do_send(std::size_t length)
	{
		socket_.async_send_to(
			asio::buffer(data_, length), s_end_point,
			[this](std::error_code /*ec*/, std::size_t /*bytes_sent*/)
		{
			do_receive();
		});
	}

private:
	udp::socket socket_;
	udp::endpoint sender_endpoint_;
	udp::endpoint sender_to;
	enum { max_length = 1500 };
	char data_[max_length];
};

int main(int argc, char* argv[])
{
	try
	{
		/*if (argc != 2)
		{
			std::cerr << "Usage: async_udp_echo_server <port>\n";
			return 1;
		}*/

		asio::io_context io_context;

		server s(io_context, 5000);

		io_context.run();
	}
	catch (std::exception& e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
	}

	return 0;
}

实验

写一个RTP发送程序,使用摄像头,摄像头转发到RTP地址的端口5000上,然后使用桥转接到外网IP地址,这里为了演示使用本机内网地址127.0.0.1,我们再使用vlc来从转发桥那里接收数据
在这里插入图片描述
在这里插入图片描述
我在程序里面使用了计数,每100个rtp包接收一次,大概每秒钟300Kbit-400Kbit左右,打开vlc接收数据
在这里插入图片描述
如图所示,vlc 正常接收到rtp程序数据以后正常播放。

这个程序的好处是无论是rtp还是gb28181 的ps流都可以正常转发。

扩展和迭代

后面再做tcp 转发,tcp的转发显然比udp 要复杂很多,,为这个程序还要制定一个http restful,里面还需要增加ssrc 等rtp包数据获取,http协议等待接收告诉服务程序需要转发哪一个rtp包, 等待下一篇吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值