Qt实现coturn穿透客户端,coturn服务器搭建

coturn简介

Coturn集成了stun+turn协议,实现NAT检测,穿透就需要通过stun协议, NAT检测无法进行穿越时就需要通过turn服务进行流媒体的转发了,而coturn就是将两者协议进行整合并进行择优优化。

STUN 协议(Simple Traversal of UDP Through NATs) 即用 UDP简单的穿透 NAT 作为一个完整的 NAT 穿透解决 方案。

网络穿透,即 NAT 穿透, 能够让公网机器找到私网机器,并提高下载速度。穿透的本质是给一个 NAT 路由器的公网 IP 地址与端口发送报文数据,对应私网机器能够收到报文数据。

TURN,英文全称是Traversal Using Relays around NAT:Relay Extensions to Session Traversal Utilities for NAT,即使用中继穿透NAT:STUN的中继扩展。
在这里插入图片描述

coturn服务器搭建

coturn服务通常搭建在公网环境,拥有可访问的公网IP,穿透成功可以获取客户端的公网IP和端口。
局域网也可以搭建coturn服务,但只能获取局域网的IP和端口,意义不大。
本章使用阿里云实验室搭建coturn,每次可用2个小时,做个demo实验足够了:阿里云实验室

sudo apt-get install openssl#安装Openssl
sudo apt-get install libssl-dev
openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes#生成cert和pkey证书
cd /root && openssl rand -writerand .rnd#Can't load /root/.rnd into RNG报错解决

git clone https://github.com/coturn/coturn.git#克隆源码
cd coturn
#安装依赖
sudo apt install pkg-config#ERROR: pkg-config
sudo apt install libssl-dev#ERROR: OpenSSL Crypto development libraries are not installed properly in required location
sudo apt install libevent-dev#ERROR: Libevent2 development libraries are not installed properly in required location
#编译
./configure
make 
sudo make install
which turnserver#查看是否安装成功

#配置环境
#turnadmin -a -u 用户名 -p 密码 -r 域名(给自己的域名)
#turnadmin -a -u test -p 123456 -r chuwei
/usr/local/bin#turnserver安装目录
cd /usr/local/etc#配置文件所在目录
sudo cp turnserver.conf.default turnserver.conf
sudo vim turnserver.conf
#添加如下内容
#网卡名
relay-device=eth0
#内网IP
listening-ip=172.16.1.193
listening-port=3478
#内网IP
relay-ip=172.16.1.193
tls-listening-port=5349
# 外网IP
external-ip=101.132.26.227
relay-threads=500
# 打开密码验证
lt-cred-mech
cert=/etc/turn_server_cert.pem
pkey=/etc/turn_server_pkey.pem
min-port=40000
max-port=65535
# 设置用户名和密码,创建IceServer时使用
user=admin:123456
# 外网IP绑定的域名
realm=101.132.26.227
# 服务器名称,用于OAuth认证,默认和realm相同,部分浏览器本段不设可能会引发cors错误。
#server-name=www.codeting.top
# 认证密码,和前面设置的密码保持一致
cli-password=123456

#turnserver -o -a -f -v -r chuwei#启动turnserver
turnserver -o -a -f#启动turnserver
netstat -ntpl#查看活跃端口,能看到启动的turnserver
lsof -i:3478#验证是否在监听

coturn服务验证

访问https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
输入coturn服务器IP和端口,用户名和密码,点击Add Server,再点击Gather candidatesm,可以看到已经获取了udp公网IP和端口。
使用的火狐浏览器,谷歌浏览器报701错误。
在这里插入图片描述
大致包含的内容:
本机 IP 地址
本机用于WebRTC通信的端口号
候选者类型,包括 host、srflx 和 relay
优先级
传输协议

candidate事件type字段取值分别为host、srflx、relay:
host(Host candidate):从本地网卡上获取的地址
srflx(Server reflexive candidate):STUN 返回的该客户端的地址
relay(Relay reflexive candidate)::TURN 服务器为该客户端分配的中继地址
本地的candidate与远端candidate构成的每一对都有一定的优先级,按优先级排序进行连通性检查。最后从有效的candidate组合中选择优先级最高的作为传输地址,用于建立P2P连接。

qt实现coturn穿透

qt实现coturn客户端,穿透成功返回公网IP和端口

#include "ccmainwindow.h"
#include "ui_ccmainwindow.h"

ccMainWindow::ccMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::ccMainWindow)
{
    ui->setupUi(this);

    pUdp = new QUdpSocket(this);

    session = (chwRtcSession*)calloc(sizeof(chwRtcSession),1);
    session->context.avinfo = (chwAVInfo*)calloc(sizeof(chwAVInfo),1);
    session->context.streamConfig = (chwStreamConfig*)calloc(sizeof(chwStreamConfig),1);
    strcpy(session->context.avinfo->rtc.iceServerIP,"101.133.145.11");
    session->context.avinfo->rtc.iceStunPort=3478;
    strcpy(session->ice.server.serverIp , "101.133.145.11");//穿透服务器IP
    session->ice.server.serverPort = 3478;//穿透服务器端口
    session->context.avinfo->rtc.hasIceServer=1;
    session->context.streamConfig->localPort = 9099;

    int err = 0;
    if(session->context.avinfo->rtc.hasIceServer&&session->ice.server.stunPort==0)
    {
        err=chw_ice_request(&session->ice.server,session->context.streamConfig->localPort);
        if(err != 0)
            printf("stun request fail!");
    }
}

ccMainWindow::~ccMainWindow()
{
    delete ui;
}


void ccMainWindow::on_pushButton_initudp_clicked()
{
    pUdp->bind(QHostAddress::Any,ui->lineEdit_localport->text().toUInt());
    connect(pUdp, SIGNAL(readyRead()),this, SLOT(readPendingDatagrams()));
}

void ccMainWindow::on_pushButton_initudp_send_clicked()
{
    pUdp->writeDatagram(ui->lineEdit_sendMsg->text().toLatin1().data(),ui->lineEdit_sendMsg->text().size(),
                        QHostAddress(ui->lineEdit_remoteIP->text()),ui->lineEdit_remotePort->text().toUInt());
    pUdp->waitForBytesWritten();
}

void ccMainWindow::readPendingDatagrams()
{
    QByteArray datagram;
    while (pUdp->hasPendingDatagrams()) {

        datagram.resize(pUdp->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        pUdp->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort);
        ui->textBrowser->append(datagram.data());
    }
}

打印输出

remoteIp=101.133.145.11,port=3478
udp server is starting,localPort=9099
stun ip=180.111.104.1,stunport=7343

NAT类型是否可以穿透

(Network Address Translation 网络 地址映射)是将 公 网地址映射为私网 地址。而能够进行映射的网络装置被称为 NAT 路由器。当我们检测到一端是端口受限锥型一端是对称型或者两端都是对称型,那肯定是无法穿越的。推荐一个NAT检测工具:NatTypeTester。
NAT类型一般分为以下4种:

  1. Full Cone NAT1 (完全圆锥型):这是最宽松的网络环境,IP和端口通常都不会受限。
  2. Address Restricted Cone NAT2 (地址限制圆锥型):相比NAT1 IP会受限,而端口不受限。
  3. Port Restricted Cone NAT3 (端口限制圆锥型):相比NAT2,NAT3 又增加了端口限制,也就是说IP、端口都会受限。
  4. Symmetric NAT4 (对称型):具有端口受限锥型的受限特性,内部地址每一次请求一个特定的外部地址,都可能会绑定到一个新的端口号。也就是请求不同的外部地址映射的端口号是可能不同的。这种类型基本上就告别 P2P 了。
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用Qt搭建服务器客户端实现直播功能时,主要需要以下几个步骤: 1. 服务器端的搭建:首先,需要通过Qt创建一个服务器应用程序,为客户端提供直播数据流的传输。使用Qt网络库类,如QTcpServer和QTcpSocket,可以实现服务器的监听和接受客户端连接请求的功能。服务器端还需使用Qt的多线程类,如QThread,来处理多个客户端连接和直播数据的发送。 2. 客户端的搭建:通过Qt创建一个客户端应用程序,用于接收服务器端传来的直播数据流并进行播放。使用Qt网络库类,如QTcpSocket,客户端能够连接服务器,并接受直播数据流。客户端还可以使用Qt的多媒体类,如QMediaPlayer,来播放从服务器传来的直播数据。 3. 直播数据的传输:一般使用TCP协议来传输直播数据。服务器端将直播数据通过TCP socket发送给已连接的客户端,而客户端则通过TCP socket接收和解析这些数据,并使用多媒体类来播放直播内容。 4. 直播功能的实现:根据需求,还可以在程序中加入一些附加功能,例如客户端的聊天室、礼物赠送、直播间管理等功能。这些功能可以通过Qt的信号与槽机制、套接字通信及数据库的操作等方式来实现。 总体而言,通过使用Qt网络库类和多媒体类,可以较为方便地搭建服务器客户端实现直播功能。在搭建过程中,需要注意处理多个连接和数据流传输的并发性,同时也需要考虑网络稳定性和性能优化等因素。 ### 回答2: 搭建服务器客户端实现直播,我们可以使用Qt网络模块来实现。 首先,在服务器端,我们需要创建一个TCP服务器。我们可以使用`QTcpServer`类来创建一个服务器,然后使用`listen`函数指定服务器的地址和端口号。当有客户端连接到服务器时,服务器会自动调用`newConnection`信号槽。 在`newConnection`槽函数中,我们可以创建一个`QTcpSocket`对象来处理与客户端的通信。我们可以使用`write`函数向客户端发送直播数据,例如视频流。同时,我们还可以使用`readyRead`信号槽来接收客户端发送的消息或命令。 在客户端,我们需要创建一个TCP客户端来连接到服务器。我们可以使用`QTcpSocket`类来创建一个客户端,然后使用`connectToHost`函数指定服务器的地址和端口号。当成功连接到服务器后,我们可以使用`connected`信号槽来进行后续操作。 在客户端中,我们可以使用`readyRead`信号槽来接收服务器发送的直播数据。我们还可以使用`write`函数向服务器发送消息或命令。 当我们的服务器客户端完成基本的连接和通信设置后,我们可以在服务器端使用多线程来处理多个客户端的连接和直播数据的传输。这样,我们就可以实现多个客户端同时观看直播。 总结起来,通过使用Qt网络模块,我们可以搭建一个简单的服务器客户端系统来实现直播功能。服务器端负责接收客户端连接,并发送直播数据,而客户端则负责连接服务器并接收直播数据。这样我们就可以实现通过搭建服务器客户端实现直播的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值