UDP、TCP

UDP

  • UDP(User Datagram Protocol,用户数据报协议)

UDP是一个轻量级、不可靠、面向数据报的、无连接的协议,多用与可靠性不严格,不是非常重要的传输。

QUdpSocket类继承自QAbstractSocket,用来发送和接收UDP数据报。

“Socket”即套接字,即IP地址+端口号。其中IP地址指定了网络中的一台主机,端口号则指定了该主机上的一个网络程序,使用套接字即可实现网络上的两个应用程序之间的通信。

QUdpSocket支持IPv4广播,要广播数据报,则只需要发送到一个特殊的地址,QHostAddress::Broadcast(255.255.255.255),数据报一般建议发送字节数小于512字节。端口号选择1024~65535(1024一下的常用作保留端口号,如FTP常用端口号21,Telnet常用端口号23,DNS域名服务器常用端口号53等)。


示例:

发送端

#include "widget.h"
#include "ui_widget.h"

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

m_sender = new QUdpSocket(this);

}

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

void Widget::on_pushButton_clicked()
{
QByteArray dataGram = ui->lineEdit->text().toUtf8();
m_sender->writeDatagram(dataGram.data(),
dataGram.size(),
QHostAddress::Broadcast,
6666);
}

接收端

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_receiver = new QUdpSocket(this);
//绑定
m_receiver->bind(6666,QUdpSocket::ShareAddress);
//有数据来了,就处理。
connect(m_receiver,&QUdpSocket::readyRead,this,&Widget::processData);
}

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

void Widget::processData()
{
//有未处理的数据报
while(m_receiver->hasPendingDatagrams()){

QByteArray dataGram;

dataGram.resize(m_receiver->pendingDatagramSize());

m_receiver->readDatagram(dataGram.data(),dataGram.size());

ui->label_2->setText(dataGram);
}
}

【QT】TCP、UDP通信_#include


TCP

  • TCP(Transmission Control Protocol,传输控制协议)

多个网络协议包括HTTP和FTP都是基于TCP协议,TCP是面向数据流和连接的可靠的传输协议。

QTcpSocket继承自QAbstractSocket,与QUdpSocket传输的数据报不同的是,QTcpSocket传输的是连续的数据流,尤其适合连续的数据传输,TCP一般分为客户端和服务端,即C/S(Client/Server)模型。

QTcpSocket代表了两个独立的数据流,一个用来读取数据,一个用来写入数据,分别采用QTcpSocket::read()及QTcpSocket::write()操作,读取数据前先调用QTcpSocket::bytesAvaliable来确定已有足够的数据可用。

QTcpServer处理客户端的连接,可通过QTcpServer::listen()监听客户端发来的连接请求,每当有客户端连接时会发射newConnection()信号,QTcpSocket可用于读取客户端发来的数据报,亦可以发送数据报。

示例:

客户端

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

const int gTcpPort = 8888;

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_tcpSocket = new QTcpSocket(this);
//收到数据开始处理
connect(m_tcpSocket,&QTcpSocket::readyRead,
this,&Widget::onReadMessage);

connect(m_tcpSocket,SIGNAL(SocketError),
this,SLOT(onDisplayError(QAbstractSocket::SocketError)));

ui->hostLineEdit->setText("127.0.0.1");

ui->portLineEdit->setText(QString::number(gTcpPort));
}

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

void Widget::onReadMessage(){
QByteArray bt;

bt.resize(m_tcpSocket->bytesAvailable());
m_tcpSocket->read(bt.data(),bt.size());//读取到bt中

ui->msgLabel->setText(bt);
}

void Widget::onDisplayError(QAbstractSocket::SocketError e){
qDebug()<<"SocketError:"<<e<<endl
<<m_tcpSocket->errorString();
}

void Widget::on_connectBtn_clicked()
{
m_tcpSocket->abort();//终止
//ip地址,端口
m_tcpSocket->connectToHost(ui->hostLineEdit->text(),gTcpPort);//链接到主机

}

void Widget::on_sendBtn_clicked()
{
m_tcpSocket->write(ui->sendLineEdit->text().toUtf8());
m_tcpSocket->flush();//清空缓冲区
}

服务端

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>


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

m_tcpServer = new QTcpServer(this);
m_tcpSocket = new QTcpSocket(this);//保存链接进来的客户端

//监听指定客户端发来的请求
if(!m_tcpServer->listen(QHostAddress::Any,8888)){
qDebug()<<m_tcpServer->errorString();
close();
}

//有新的链接请求
connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onNewConnect);

// 给链接的客户端反馈信息
connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onSendMessage);


}

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

void Widget::onNewConnect()
{

m_tcpSocket = m_tcpServer->nextPendingConnection();//获取当前新来的链接

//断开链接——销毁
connect(m_tcpSocket,&QTcpSocket::disconnected,m_tcpServer,&QTcpSocket::deleteLater);

//来消息后发送readyRead信号,与读取数据方法进行链接
connect(m_tcpSocket,&QTcpSocket::readyRead,this,&Widget::onReadMessage);
}

void Widget::onSendMessage()
{
QString str = "你好,client";
m_tcpSocket->write(str.toUtf8());//写入socket
ui->label->setText("发送数据成功!");


}

void Widget::onReadMessage()
{
QByteArray bt = m_tcpSocket->readAll();
ui->readLabel->setText(bt);
}

【QT】TCP、UDP通信_#include_02