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

目录

  • coturn简介
  • coturn服务器搭建
  • coturn服务验证
  • qt实现coturn穿透
  • NAT类型是否可以穿透

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的中继扩展。
Qt实现coturn穿透客户端,coturn服务器搭建_第1张图片

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错误。
Qt实现coturn穿透客户端,coturn服务器搭建_第2张图片
大致包含的内容:
本机 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 了。

你可能感兴趣的:(音视频,qt,服务器,网络)