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

环境搭建等参考:JRTP实时音视频传输(1)-必做的环境搭建与demo测试

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  58008int 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;}//初始化socketint 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  58008void 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 packetsif (m_RTPTCPSession.GotoFirstSourceWithData()){do{RTPPacket *pack;while ((pack = m_RTPTCPSession.GetNextPacket()) != NULL){// You can examine the data hereprintf("myserver recv packet buf:%s, len:%d\n", pack->GetPayloadData(), pack->GetPayloadLength());// we don't longer need the packet, so// we'll delete itm_RTPTCPSession.DeletePacket(pack);}} while (m_RTPTCPSession.GotoNextSourceWithData());}m_RTPTCPSession.EndDataAccess();#ifndef RTP_SUPPORT_THREADstatus = m_RTPTCPSession.Poll();checkerror(status);
#endif // RTP_SUPPORT_THREADRTPTime::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~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

79、avx2 向量指令集优化卷积运算

上一节 介绍了 avx2 向量指令集中的 load/store 操作,本节介绍如何使用 avx2 的向量指令集来实现乘累加运算。 因为我们实战中用到的 resnet50 神经网络中,卷积运算在整个模型中的比例占据是相当高,而卷积运算的核心计算就是乘累加计算。因此,只要将最核心的乘累加计算效率…

2024成都线路板展览会|全国线路板展

时 间&#xff1a;2024年7月17&#xff5e;19日 地 点&#xff1a;成都世纪城新国际会展中心 ◆ 》》》展会概况&#xff1a; 电路板是电子产品的关键电子互联件&#xff0c;被誉为“电子产品之母”。电路板行业作为电子信息产业中重要的组成部分&#xff0c;受到国家产…

怎么从视频中提取动图?一个方法快速提取gif

视频以连续的方式播放一系列图像帧&#xff0c;通过每秒播放的帧数&#xff08;帧率&#xff09;来创做&#xff0c;由于GIF动图则以循环播放一系列静态图像帧的方式展现动画效果。由于视频的优势在于流畅的动画、丰富的细节和长时间播放&#xff0c;因此常用于电影、电视节目、…

React Hooks 基本使用

背景 class 组件如果业务复杂&#xff0c;很难拆分和重构&#xff0c;很难测试&#xff1b;相同业务逻辑分散到各个方法中&#xff0c;逻辑混乱逻辑复用像HOC、Render Props&#xff0c;不易理解&#xff0c;学习成本高React提倡函数式编程&#xff0c;函数更易拆分&#xff0…

如何在 Ubuntu / Raspbian 上安装 MariaDB

Raspberry Pi OS&#xff08;原为Raspbian&#xff09;是为树莓派基于Debian开发的操作系统。 从2015年起&#xff0c;树莓派基金会正式将其作为树莓派的官方操作系统。 Raspbian是由Mike Thompson和Peter Green创建的一个独立项目。第一个版本于2012年6月发布&#xff0c;至…

LP-AM243x EtherNet/IP 连接施耐德 M241 EIP主站测试

硬件环境&#xff1a;LP-AM243x 开发板 施耐德 Modicon M241 软件环境&#xff1a; INDUSTRIAL-COMMUNICATIONS-SDK-AM243X MCU-PLUS-SDK-AM243X — MCU SDK for AM243x 调试过程&#xff1a; 首先&#xff0c;让AM243x能够运行 Null Boot&#xff0c; Starting NULL Boo…

大数据小白初探Hbase从零到入门

目录 1.前言 2.初识Hbase 2.1 有了HDFS为什么还需要HBase呢? 2.2 HBase主要做什么的? 2.3 HBase架构特点? 2.4 HBase的适用场景? 2.5 HBase的数据模型和物理储存格式? 2.5.1 逻辑表结构 2.5.2 物理存储 2.5.3 分布式集群框架部署图 2.5.4 HBase的逻辑本质: 2…

Python 循环结构练习-穷举法

穷举法&#xff1a;穷尽所有的可能性&#xff0c;然后设置条件&#xff0c;找到问题的解 —> 暴力破解法 题目1&#xff1a;鸡翁一值钱5&#xff0c;鸡母一值钱3&#xff0c;鸡雏三值钱1&#xff0c;用百钱买百鸡&#xff0c;问鸡翁、鸡母、鸡雏几何。 实现&#xff1a; …

Kotlin 尾递归函数

函数式编程中&#xff0c;重要的概念 尾递归。 当一个函数&#xff0c;在函数最后调用 自身&#xff0c;称为 尾递归&#xff0c;是一种特殊的递归函数。 在JVM中&#xff0c;每次方法调用时&#xff0c;都会产生新的栈帧&#xff08;stack frame&#xff09;&#xff0c;消耗栈…

TCP缓存(C++)

系统为每个 socket 创建了发送缓冲区和接收缓冲区&#xff0c;应用程序调用 send()/write()函数发送数据的 时候&#xff0c;内核把数据从应用进程拷贝 socket 的发送缓冲区中&#xff1b;应用程序调用 recv()/read()函数接收数据的时候&#xff0c;内核把数据从 socket 的接收…

C语言实现简单的扫雷游戏

目录 1 -> test.c 2 -> game.c 3 -> game.h 1 -> test.c #define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu() {printf("************************************\n");printf("********* 1.play ********\n&quo…

【51单片机】动态数码管

0、前言 参考&#xff1a; 普中51单片机开发攻略–A2.pdf 1、数码管介绍 上一章我们主要是介绍一位数码管的内部结构及控制原理。下面我们再来介 绍下多位数码管及动态显示原理的相关知识。 1.1 多位数码管简介 2、74HC245 和 74HC138 芯片介绍 2.1 74HC245 芯片简介 2.2 7…

nginx 搭建docker 似有hub仓库

当使用 SSL/TLS 证书并希望通过 HTTPS 访问 Docker Registry 时&#xff0c;通常会使用 Nginx 作为反向代理。这样做可以为 Docker Registry 提供 HTTPS 支持&#xff0c;同时还可以利用 Nginx 的其他功能&#xff0c;如负载均衡和缓存。下面是使用 Nginx 作为反向代理设置私有…

Docker使用及部署python项目

一、准备项目 ​ 我写的是一个爬取某ppt网站的代码&#xff0c;就一个ppt1.py是爬虫&#xff0c;然后&#xff0c;ppts是存放下载的ppt的 二、准备requirement.txt文件 这个是需要哪些python库支持&#xff0c;写好 ​ 三、准备Dockerfile文件 需要一个名为Dockerfile的文件&…

HarmonyOS关于deps、external_deps的使用

在添加一个模块的时候&#xff0c;需要在BUILD.gn中声明它的依赖&#xff0c;为了便于后续处理部件间依赖关系&#xff0c;我们将依赖分为两种——部件内依赖deps和部件间依赖external_deps。 依赖分类 如上图所示&#xff0c;主要分为部件内依赖&#xff08;图左&#xff09;…

Java设计模式-前言

大家好&#xff0c;我是馆长&#xff01;从今天开始馆长开始对java设计模式进行讲解和整理分享给大家。馆长会尽快的整理完成设计模式的所有内容和讲解代码。从多方面进行模式的详细说明&#xff0c;方便各位看官理解和易学。 软件设计模式的概念 软件设计模式&#xff08;Sof…

C++笔记之bool类型的隐式转换现象与应用

C++笔记之bool类型的隐式转换现象与应用 —— 《C++ Primer Plus》 文章目录 C++笔记之bool类型的隐式转换现象与应用1.C++中,有几种类型和表达式可以隐式转换为bool类型2.使用explicit关键字来声明显示转换运算符,这样只有在使用static_cast<bool>时才能将对象转换为…

MySQL之索引结构

索引概述 索引是帮助MySQL高效获取数据的数据结构&#xff08;有序&#xff09;。 在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c;这样就可以在这些数据结构上实现…

00-Rust前言

问&#xff1a;为什么要近期想学习Rust? 答&#xff1a; Rust出来也是有一段时间了&#xff0c;从Microsoft吵着要重构他们的C"祖传代码"开始&#xff0c;Rust就披着“高效&#xff0c;安全”的头衔。而自己决定要学习Rust&#xff0c;是因为近期发现&#xff1a;涉…

技术方案——参考模板

我认为写好一个技术方案&#xff0c;对于开发同学来说至关重要&#xff0c;不仅可以帮助我们做好需求&#xff0c;更能帮助我们锻炼自己的文字功底。 在接手需求时&#xff0c;我们很难做到每一次都对需求的影响面都十分清楚&#xff0c;更多的都是要借助团队的力量&#xff0…