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等)。
示例:
发送端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #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); }
|
接收端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #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); } }
|
![image-20220323121512761](https://gitee.com/Do2eM0N/blogimg/raw/master/202203231215830.png)
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可用于读取客户端发来的数据报,亦可以发送数据报。
示例:
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #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());
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(); m_tcpSocket->connectToHost(ui->hostLineEdit->text(),gTcpPort);
}
void Widget::on_sendBtn_clicked() { m_tcpSocket->write(ui->sendLineEdit->text().toUtf8()); m_tcpSocket->flush(); }
|
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #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);
connect(m_tcpSocket,&QTcpSocket::readyRead,this,&Widget::onReadMessage); }
void Widget::onSendMessage() { QString str = "你好,client"; m_tcpSocket->write(str.toUtf8()); ui->label->setText("发送数据成功!");
}
void Widget::onReadMessage() { QByteArray bt = m_tcpSocket->readAll(); ui->readLabel->setText(bt); }
|
![image-20220323215110060](https://gitee.com/Do2eM0N/blogimg/raw/master/202203232151137.png)