JRTP实时音视频传输(2)-使用TCP通信的案例

1.创建自己的demo

先将example1拷贝为myclienttcp.cpp和myservertcp.cpp
cp example1.cpp myclienttcp.cpp
cp example1.cpp myservertcp.cpp

改写jrtplib/JRTPLIB/examples/CMakeLists.txt,添加myclienttcp和myservertcp编译
image.png
重新生成Makefile并编译

sudo cmake CMakeLists.txt
sudo make

可以看到成功编译了myclienttcp和myservertcp源文件
image.png
编译通过,这里就去实现demo就行

2.demo源码-客户端

#include <iostream>
#include <arpa/inet.h>
#include "rtptcpaddress.h"
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtptcptransmitter.h"
#include "rtpipv4address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include "rtpabortdescriptors.h"

using namespace jrtplib;

#define SERVER_IP    "127.0.0.1"
#define SERVER_PORT  58008

int main()
{
    RTPSession session;
    RTPAbortDescriptors m_descriptors;

    RTPSessionParams sessionparams;
    sessionparams.SetAcceptOwnPackets(true);
    sessionparams.SetOwnTimestampUnit(1.0/10.0);

    m_descriptors.Init();

    RTPTCPTransmissionParams transparams;
    transparams.SetCreatedAbortDescriptors(&m_descriptors);
    int status = session.Create(sessionparams,&transparams,RTPTransmitter::TCPProto);

    if (status < 0)
    {
        printf("my client session create failed\n");
        return -1;
    }

    //初始化socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in addrSrv;
    addrSrv.sin_addr.s_addr = inet_addr(SERVER_IP);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(SERVER_PORT);

    printf("my client prepare to connect\n");

    //连接服务器
    connect( sock, (sockaddr*)&addrSrv, sizeof(sockaddr));

    RTPTCPAddress addr(sock);

    status = session.AddDestination(addr);
    if (status < 0)
    {
        printf("my client session add destination failed\n");
        return -1;
    }

    session.SetDefaultPayloadType(96);
    session.SetDefaultMark(false);
    session.SetDefaultTimestampIncrement(160);

    for (int i = 0; i < 50 ; i++)
        {
            std::string str("123456");
            //发送数据
            session.SendPacket((void *)str.c_str(), str.length(),0,false,10);

            printf("my client send packet:%s, len:%d, idx:%d\n", str.c_str(), str.length(), i);
            RTPTime::Wait(RTPTime(10, 0));
        }

    RTPTime delay(0.020);
    session.BYEDestroy(delay,"Client End",9);
}

3.demo源码-服务端

/*
   Here's a small IPv4 example: it asks for a portbase and a destination and 
   starts sending packets to that destination.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include "rtppacket.h"
#include "rtptcpaddress.h"
#include "rtptcptransmitter.h"
#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtplibraryversion.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

#define SERVER_PORT  58008

void checkerror(int rtperr)
{
	if (rtperr < 0)
	{
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}

int main(void)
{
    int   nListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (nListener == -1)
	{
		return  -1;
	}
 
	sockaddr_in   serverAddr;
	memset(&serverAddr, 0, sizeof(sockaddr_in));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = INADDR_ANY;
	serverAddr.sin_port = htons(SERVER_PORT);
	int  nRet = bind(nListener, (sockaddr*)&serverAddr, sizeof(serverAddr));
	if (nRet == -1)
	{
		return  -1;
	}
	if (listen(nListener, 1) == -1)
	{
		return  -1;
	}
 
	printf("my server is listen ready, wait for connect\n");

	sockaddr_in   clientAddr;
	int  nLen = sizeof(sockaddr_in);
	int   nServer = -1;
	while (true)
	{
		nServer = accept(nListener, (sockaddr*)&clientAddr, (socklen_t *)&nLen);
		if (nServer == -1)
		{
			continue;
		}
		else
		{
			break;
		}
	}
	printf("my server connect new client\n");

	int status = -1;
	int  nPackSize = 45678;
	RTPSessionParams   sessparams;
	RTPSession m_RTPTCPSession;

	sessparams.SetProbationType(RTPSources::NoProbation);
	sessparams.SetOwnTimestampUnit(90000.0 / 25.0);
	sessparams.SetMaximumPacketSize(nPackSize + 64);

	RTPTCPTransmitter    *pTransparams =  new RTPTCPTransmitter(NULL);
	status = pTransparams->Init(false);
	if (status < 0)
	{
		printf("my server trans param init failed, reason:%s\n", RTPGetErrorString(status).c_str());
        return -1;		
	}
	status = pTransparams->Create(65535, NULL);
	if (status < 0)
	{
        printf("my server trans param create failed, reason:%s\n", RTPGetErrorString(status).c_str());
        return -1;		
	}

	status = m_RTPTCPSession.Create(sessparams, pTransparams);
	if (status < 0)
	{
        printf("my server trans session create failed, reason:%s\n", RTPGetErrorString(status).c_str());
        return -1;		
	}
	status = m_RTPTCPSession.AddDestination(RTPTCPAddress(nServer));
	if (status < 0)
	{
        printf("my server trans session add failed, reason:%s\n", RTPGetErrorString(status).c_str());
        return -1;		
	}

	while (1)
	{	
		m_RTPTCPSession.BeginDataAccess();
		
		// check incoming packets
		if (m_RTPTCPSession.GotoFirstSourceWithData())
		{
			do
			{
				RTPPacket *pack;
				
				while ((pack = m_RTPTCPSession.GetNextPacket()) != NULL)
				{
					// You can examine the data here
					printf("myserver recv packet buf:%s, len:%d\n", pack->GetPayloadData(), pack->GetPayloadLength());
					
					// we don't longer need the packet, so
					// we'll delete it
					m_RTPTCPSession.DeletePacket(pack);
				}
			} while (m_RTPTCPSession.GotoNextSourceWithData());
		}
		
		m_RTPTCPSession.EndDataAccess();

#ifndef RTP_SUPPORT_THREAD
		status = m_RTPTCPSession.Poll();
		checkerror(status);
#endif // RTP_SUPPORT_THREAD
		
		RTPTime::Wait(RTPTime(1,0));
	}
	
	m_RTPTCPSession.BYEDestroy(RTPTime(10,0),0,0);

	return 0;
}


4.demo运行测试

分别运行client和server ,可以看到数据正常传输到server端
image.png
用netstat查看连接端口信息,也能看到该端口目前的状态,属于TCP连接,实验成功
image.png

对环境搭建不清楚的可以看这篇博客~
JRTP实时音视频传输(1)-必做的环境搭建与demo测试

5.源码下载

哈喽~我是Embedded-Xin,沪漂嵌入式开发工程师一枚,立志成为嵌入式全栈开发工程师,成为优秀博客创作者,共同学习进步。
以上代码全部放在我私人的github地址,其中有许多自己辛苦敲的例程源码,供大家参考、批评指正,有兴趣还可以直接提patch修改我的仓库~:
https://github.com/Xuzhangxin/study_linux_project.git
觉得不错的话可以点个收藏和star~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/330262.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

plc红绿灯程序

引言&#xff1a; PLC&#xff08;Programmable Logic Controller&#xff0c;可编程逻辑控制器&#xff09;是一种用于工业自动化控制的电子设备。西门子的SIMATIC S7-200是这类设备的一个流行系列&#xff0c;广泛应用于小型至中等规模的自动化项目中。它具有以下特点&#…

pytorch学习(一)线性模型

文章目录 线性模型 pytorch是一个基础的python的科学计算库&#xff0c;它有以下特点&#xff1a; 类似于numpy&#xff0c;但是它可以使用GPU可以用它来定义深度学习模型&#xff0c;可以灵活的进行深度学习模型的训练和使用 线性模型 线性模型的基本形式为&#xff1a; f ( x…

推荐一款性价比高的USB 协议分析仪

最近在入门学习USB 协议&#xff0c;USB 协议是出了名的晦涩难懂&#xff0c;调试过程中如果没有合适的工具帮助分析&#xff0c;就像电工没有电表笔一样&#xff0c;难以诊断各种奇难杂症。 于是网上找了一下USB 协议分析仪&#xff0c;一看价格超过3位数的就不考虑了&#x…

Java关键字static和final

一、final关键字是什么&#xff1f; 1、final可以用来修饰的结构&#xff1a;类、方法、变量 2、final用来修饰一个类&#xff1a;此类不能被其它类继承。当我们需要让一个类永远不被继承&#xff0c;此时就可以用final修饰&#xff0c;但要注意&#xff1a;final类中所有的成…

ArcGIS Pro 如何新建布局

你是否已经习惯了在ArcGIS中数据视图和布局视图之间来回切换&#xff0c;到了ArcGIS Pro中却找不到二者之间切换的按钮&#xff0c;即使新建布局后却发现地图怎么却是一片空白。 这一切的一切都是因为ArcGIS Pro的功能框架完全不同&#xff0c;这里为大家介绍一下在ArcGIS Pro…

微信小程序(五)下拉刷新

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1. 下拉刷新 2. 下拉页面背景颜色 3. 设置是否可滚动 4. 设置导航栏模式 源码&#xff1a;(实际上不能加注释但这里为了方便解释就加上了) index.json {//默认模式&#xff0c;另一种自定义模式是custom//自定义…

课表排课小程序怎么制作?多少钱?

在当今的数字化时代&#xff0c;无论是购物、支付、点餐&#xff0c;还是工作、学习&#xff0c;都离不开各种各样的微信小程序。其中&#xff0c;课表排课小程序就是许多教育机构和学校必不可少的工具。那么课表排课小程序怎么制作呢&#xff1f;又需要多少钱呢&#xff1f; …

RK3399平台入门到精通系列讲解(USB篇)UDC 层 usb_gadget_probe_driver 接口分析

🚀返回总目录 文章目录 一、UDC:usb_gadget_probe_driver函数分析二、usb_gadget_driver 结构详细介绍三、usb_udc 结构详细介绍一、UDC:usb_gadget_probe_driver函数分析 UDC层的一项基本任务是向上层提供usb_gadget_probe_driver()接口函数。 上层调用者为composite.c中…

坚持刷题 | 二叉树的层序遍历

坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天刷&#xff1a;二叉树的层序遍历 题目 102二叉树的层序遍历 考察点 数据结构基础&#xff1a; 能够正确地使用二叉树数据结构&#xff0c;并了解二叉树的基本性质。编程基础&#xff1a; 能够熟练使用Java编程语言&a…

【linux】Debian10.0配置vsftpd

一、基本步骤 在 Debian 10 (Buster) 上要配置 vsftpd (Very Secure FTP Daemon)&#xff0c;请按照以下步骤操作&#xff1a; 1. 安装 vsftpd: sudo apt update sudo apt install vsftpd 2. 在启动配置之前&#xff0c;建议备份原始的配置文件: sudo cp /etc/vsftpd.con…

2024美赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--具身智能、强化学习

专属领域论文订阅 VX关注 晓理紫&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 分类: 大语言模型LLM视觉模型VLM扩散模型视觉导航具身智能&#xff0c;机器人强化学习开放词汇&#xff0c;检测分割 [晓理紫]每日论文分享…

【机器学习300问】9、梯度下降是用来干嘛的?

当你和我一样对自己问出这个问题后&#xff0c;分析一下&#xff01;其实我首先得知道梯度下降是什么&#xff0c;也就它的定义。其次我得了解它具体用在什么地方&#xff0c;也就是使用场景。最后才是这个问题&#xff0c;梯度下降有什么用&#xff1f;怎么用&#xff1f; 所以…

02--数据库事务

1、数据库事务 1.1 数据库事务介绍 事务&#xff1a;一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理&#xff08;事务操作&#xff09;&#xff1a;保证所有事务都作为一个工作单元来执行&#xff0c;即使出现了故障&#xff0c;都不能改变这种执行方式。当…

【分布式技术】分布式存储ceph之RGW接口

目录 1、对象存储概念 2、创建 RGW 接口 //在管理节点创建一个 RGW 守护进程 #创建成功后默认情况下会自动创建一系列用于 RGW 的存储池 #默认情况下 RGW 监听 7480 号端口 //开启 httphttps &#xff0c;更改监听端口 #更改监听端口 ​ //创建 RadosGW 账户 …

STM32F103标准外设库——中断应用/事件控制器(六)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

【记录】解决 git 仓库突然出现连接失败

问题描述 今天在 push 代码代码的时候突然发现无法 push(但是我可以正常打开 Gihub)&#xff0c;这可不行&#xff0c;我可是 git 的重度使用者&#x1f60d;&#xff0c;我所有的代码都托管在了 Github 上&#xff0c;没有它我的日子怎么活啊&#xff01;&#xff01;&#x…

Unity向量叉乘

叉乘计算公式 Unity中叉乘计算 Vector3.Cross(A.position, B.position); 几何意义 假设向量A和B 都在XZ平面上 向量A叉乘向量B y大于0 证明 B在A右侧 y小于0 证明 B在A左侧 示例 Vector3 C Vector3.Cross(A.position, B.position); if(C.y > 0) {print("B在A右侧&qu…

【不需要网络不需要显卡】本地部署GPT

【不需要网络/不需要显卡】本地部署GPT 大家好&#xff0c;我是老 J 我们都知道ChatGPT目前只有两种使用方式&#xff0c;一种是直接去官网访问&#xff0c;适合个人用户&#xff1b;另一种是API调用&#xff0c;适合企业或者网站使用。这两种方式的门槛都比较高&#xff0c;…

修改iview的表格table展开的默认icon和样式

修改前 修改后 修改内容 .title_label_list .ivu-icon-ios-add{font-size: 26px;color: #888888; } .title_label_list .ivu-icon-ios-add:hover{color: #11AAAA; } .title_label_list .ivu-icon-ios-add:before {content: "\F341"; } .title_label_list .ivu-icon-…