Qt 学习笔记 - 第四章 - Qt的三驾马车之 - 网络编程
Qt 学习笔记全系列传送门:
1、TCP 通信
1.1 TCP 编程的特点
- 包含服务器和客户端
- 使用时需要在工程文件中引入
QT += network
并在使用时导入包 - 需要使用到的类有
- QTcpServer
- QTcpSocket
1.2 TCP 服务器案例
需要先定义并在构造中初始化
QTcpServer *tcpServer
和QTcpSocket *tcpSocket
:// 这里传入 this 时,父对象被删除时子对象也会被删除,省去了delete的麻烦 tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this);
-
工程文件
QT += core gui network
-
UI
-
接收框,只读
-
端口号输入框和提示文字
-
发送窗口
-
按钮,打开服务器、关闭服务器、发送
-
控件改名
-
-
逻辑功能
-
监听:槽函数,点击打开服务器时,需要监听对应端口是否被访问
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 新建tcpServer和tcpSocket的对象,成员属性在头文件中已定义,细节不表 tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); } void Widget::on_openBt_clicked() { // 开启监听,监听所有人的连接,参数指定所有人和一个无符号整型端口 tcpServer->listen(QHostAddress::Any, ui->portEdit->text().toUInt()); }
-
接收:包含获取和展示两个部分
-
获取
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); // 当监测到新的连接产生的信号时,调用槽函数newConnection_Slot() connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection_Slot())); } void Widget::newConnection_Slot() { // 获取到已经连接的客户端的Socket tcpSocket = tcpServer->nextPendingConnection(); // 当存在可读数据时,调用槽函数readyRead_Slot(),用于展示到接收框中 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); }
-
展示到接收框
void Widget::readyRead_Slot() { // 读取tcpSocket中的内容,使用字符串接收 QString buf = tcpSocket->readAll(); // 将读取到的信息展示到接收框中 ui->recvEdit->appendPlainText(buf); }
-
-
发送
void Widget::on_sendBt_clicked() { // 需要转成 char* tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); }
-
关闭
void Widget::on_closeBt_clicked() { tcpServer->close(); tcpSocket->close(); }
-
1.3 TCP 客户端案例
-
工程文件
QT += core gui network
-
UI
-
接收框,只读
-
端口号输入框和提示文字、IP地址输入框和提示文字
-
发送窗口
-
按钮,打开服务器、关闭服务器、发送
-
控件改名
-
-
逻辑功能
需要先定义并在构造中初始化
QTcpSocket *tcpSocket
:
tcpSocket = new QTcpSocket(this);
-
连接
void Widget::on_openBt_clicked() { // 点击打开客户端时,应连接服务器,取界面上的ip和端口,端口要转Uint tcpSocket->connectToHost(ui->ipEdit->text(), ui->portEdit->text().toUInt()); // 当监听到连接成功的信号connected()时,调用槽函数connected_Slot() connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected_Slot())); }
-
接收
void Widget::connected_Slot() { // 当监听到有东西可读的信号readyRead()时,调用槽函数 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } void Widget::readyRead_Slot() { // 读取tcpSocket中的信息,展示到页面上 ui->recvEdit->appendPlainText(tcpSocket->readAll()); }
-
发送
void Widget::on_sendBt_clicked() { // 发送时将发送框中的内容转为 char* 写入tcpSocket tcpSocket->write(ui->sendEdit->text().toLocal8Bit()); }
-
关闭
void Widget::on_closeBt_clicked() { tcpSocket->close(); }
-
2、UDP 通信
1.1 UDP 编程的特点
-
不分客户端和服务器
-
使用时需要在工程文件中引入
QT += network
并在使用时导入包 -
需要使用 QUdpSocket 类
1.2 UDP 客户端
需要先定义并在构造中初始化
QUdpSocket *udpSocket
:
udpSocket = new QUdpSocket(this);
-
工程文件
QT += core gui network
-
UI
- 接收框,只读
- 端口号输入框和提示文字、目标端口号输入框和提示文字、IP地址输入框和提示文字
- 发送窗口
- 按钮,打开服务器、关闭服务器、发送
- 控件改名
-
逻辑功能
-
启动
void Widget::on_openBt_clicked() { // 将端口号绑定到Socket if (udpSocket->bind(ui->localPortEdit->text().toUInt())) { QMessageBox::information(this, "提示", "成功"); } else { QMessageBox::information(this, "提示", "失败"); } // 关联readyRead信号,有可读信号调用槽函数 connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot())); }
-
接收
void Widget::readyRead_slot() { // hasPendingDatagrams()用于判断是否读取完,若没有读完则返回true while (udpSocket->hasPendingDatagrams()) { QByteArray arr; // 将数组调整为和 udpSocket 中剩下的数据大小一样 arr.resize(udpSocket->pendingDatagramSize()); // 将udpSocket中的信息读取到arr中,参数为接收数组和接收的数据长度 udpSocket->readDatagram(arr.data(), arr.size()); // 将信息写到页面上 QString buffer = arr.data(); ui->recvEdit->appendPlainText(buffer); } }
-
发送
void Widget::on_sendBt_clicked() { qunit16 port = ui->aimPortEdit->text().toUInt(); QString sendbuffer = ui->sendEdit->text(); QHostAddress addr; addr.setAddress(ui->aimIpEdit->text()); // 发送的内容需要转成 char* udpSocket->writeDatagram(sendbuffer.toLocal8Bit().data(), sendbuffer.length(), addr, port); }
-
关闭
void Widget::on_closeBt_clicked() { udpSocket->close(); }
-