【QT】TCP、UDP通信
原创
©著作权归作者所有:来自51CTO博客作者半生瓜的blog的原创作品,请联系作者获取转载授权,否则将追究法律责任
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);
}
}
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);
}