首页
文章
留言
首页
文章
留言
Qt实现TCP通讯
2016 年 11 月 19 日
桌面应用
程序开发
C++
Qt
GUI
Qt 是一个跨平台 C++ 图形用户界面应用程序开发框架。它既可以开发 GUI 程序,也可用于开发非 GUI 程序,比如控制台工具和服务器。最近总结了下使用 Qt 来实现了 TCP 通讯,编写了一个客户端和服务器基于窗口通信的小程序。 #### 使用前配置 使用 Qt 网络功能需要在 `.pro` 文件增加网络库: ``` QT += network ``` #### 服务端 ##### 1、服务端用到了 QTcpSocket、QTcpSever 类。主要用到了6个步骤: (1)创建 QTcpSever 对象。 ```cpp server = new QTcpServer(); ``` (2)侦听一个端口,使得客户端可以使用这个端口访问服务端。 ```cpp server->listen(QHostAddress::Any, port) ``` (3)当服务端被客户端访问时,会发出 newConnection() 信号,因此为该信号添加槽函数,并用一个 QTcpSocket 对象接受客户端访问。 ```cpp connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect); void MainWindow::server_New_Connect() { // 获取客户端连接 socket = server->nextPendingConnection(); } ``` (4)使用 `socket` 的 `write` 函数向客户端发送数据。 ```cpp socket->write(data); ``` (5)当 `socket` 接收缓冲区有新数据到来时,会发出 `readRead()` 信号,因此为该信号添加槽函数以读取数据。 ```cpp QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); void MainWindow::socket_Read_Data() { QByteArray buffer; // 读取缓冲区数据 buffer = socket->readAll(); } ``` (6)取消侦听。 ```cpp server->close(); ``` ##### 2、以下是服务器的源码文件 首先是 mainwindow.h 文件: ```cpp // mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include
#include
#include
namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_pushButton_Listen_clicked(); void on_pushButton_Send_clicked(); void server_New_Connect(); void socket_Read_Data(); void socket_Disconnected(); private: Ui::MainWindow *ui; QTcpServer* server; QTcpSocket* socket; }; #endif // MAINWINDOW_H ``` 然后是 mainwindow.cpp 文件: ```cpp #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->lineEdit_Port->setText("8765"); ui->pushButton_Send->setEnabled(false); server = new QTcpServer(); // 连接信号槽 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect); } MainWindow::~MainWindow() { server->close(); server->deleteLater(); delete ui; } void MainWindow::on_pushButton_Listen_clicked() { if(ui->pushButton_Listen->text() == tr("侦听")) { // 从输入框获取端口号 int port = ui->lineEdit_Port->text().toInt(); // 监听指定的端口 if(!server->listen(QHostAddress::Any, port)) { // 若出错,则输出错误信息 qDebug()<
errorString(); return; } // 修改按键文字 ui->pushButton_Listen->setText("取消侦听"); qDebug()<< "Listen succeessfully!"; } else { // 如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30) if(socket->state() == QAbstractSocket::ConnectedState) { // 关闭连接 socket->disconnectFromHost(); } // 取消侦听 server->close(); // 修改按键文字 ui->pushButton_Listen->setText("侦听"); // 发送按键失能 ui->pushButton_Send->setEnabled(false); } } void MainWindow::on_pushButton_Send_clicked() { qDebug() << "Send: " << ui->textEdit_Send->toPlainText(); // 获取文本框内容并以ASCII码形式发送 socket->write(ui->textEdit_Send->toPlainText().toLatin1()); socket->flush(); } void MainWindow::server_New_Connect() { // 获取客户端连接 socket = server->nextPendingConnection(); // 连接QTcpSocket的信号槽,以读取新数据 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected); // 发送按键使能 ui->pushButton_Send->setEnabled(true); qDebug() << "A Client connect!"; } void MainWindow::socket_Read_Data() { QByteArray buffer; // 读取缓冲区数据 buffer = socket->readAll(); if(!buffer.isEmpty()) { QString str = ui->textEdit_Recv->toPlainText(); str+=tr(buffer); // 刷新显示 ui->textEdit_Recv->setText(str); } } void MainWindow::socket_Disconnected() { // 发送按键失能 ui->pushButton_Send->setEnabled(false); qDebug() << "Disconnected!"; } ``` #### 客户端 ##### 1、客户端的代码比服务端稍简单,使用QT中的QTcpSocket类与服务端进行通信只需要以下5步: (1)创建 QTcpSocket 套接字对象。 ```cpp socket = new QTcpSocket(); ``` (2)使用这个对象连接服务端。 ```cpp socket->connectToHost(IP, port); ``` (3)使用write函数向服务端发送数据。 ```cpp socket->write(data); ``` (4)当 `socket` 接收缓冲区有新数据到来时,会发出 `readRead()` 信号,因此为该信号添加槽函数以读取数据。 ```cpp QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); void MainWindow::socket_Read_Data() { QByteArray buffer; // 读取缓冲区数据 buffer = socket->readAll(); } ``` (5)断开与服务端的连接。(关于close()和disconnectFromHost()的区别,可以按F1看帮助) ```cpp socket->disconnectFromHost(); ``` ##### 2、以下是客户端的源码文件 首先是mainwindow.h文件: ```cpp // mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include
#include
namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_pushButton_Connect_clicked(); void on_pushButton_Send_clicked(); void socket_Read_Data(); void socket_Disconnected(); private: Ui::MainWindow *ui; QTcpSocket *socket; }; #endif // MAINWINDOW_H ``` 然后是 mainwindow.cpp 文件: ```cpp // mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); socket = new QTcpSocket(); // 连接信号槽 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected); ui->pushButton_Send->setEnabled(false); ui->lineEdit_IP->setText("127.0.0.1"); ui->lineEdit_Port->setText("8765"); } MainWindow::~MainWindow() { delete this->socket; delete ui; } void MainWindow::on_pushButton_Connect_clicked() { if(ui->pushButton_Connect->text() == tr("连接")) { QString IP; int port; // 获取IP地址 IP = ui->lineEdit_IP->text(); // 获取端口号 port = ui->lineEdit_Port->text().toInt(); // 取消已有的连接 socket->abort(); // 连接服务器 socket->connectToHost(IP, port); // 等待连接成功 if(!socket->waitForConnected(30000)) { qDebug() << "Connection failed!"; return; } qDebug() << "Connect successfully!"; // 发送按键使能 ui->pushButton_Send->setEnabled(true); // 修改按键文字 ui->pushButton_Connect->setText("断开连接"); } else { // 断开连接 socket->disconnectFromHost(); // 修改按键文字 ui->pushButton_Connect->setText("连接"); ui->pushButton_Send->setEnabled(false); } } void MainWindow::on_pushButton_Send_clicked() { qDebug() << "Send: " << ui->textEdit_Send->toPlainText(); // 获取文本框内容并以ASCII码形式发送 socket->write(ui->textEdit_Send->toPlainText().toLatin1()); socket->flush(); } void MainWindow::socket_Read_Data() { QByteArray buffer; // 读取缓冲区数据 buffer = socket->readAll(); if(!buffer.isEmpty()) { QString str = ui->textEdit_Recv->toPlainText(); str+=tr(buffer); // 刷新显示 ui->textEdit_Recv->setText(str); } } void MainWindow::socket_Disconnected() { // 发送按键失能 ui->pushButton_Send->setEnabled(false); // 修改按键文字 ui->pushButton_Connect->setText("连接"); qDebug() << "Disconnected!"; } ```
0
相关文章
macOS常用命令
Git使用总结
C/C++基础知识总结
全部分类
前端
后端
运维
架构
算法
数据库
移动应用
桌面应用
程序开发
热门标签
iOS
Kafka
Shell
Redis
Android
Python
GUI
C++
MongoDB
Linux
多线程
Nginx
Git
Supervisor
Docker
Lua
CSS
CentOS
macOS
Qt
Composer
Elasticsearch
JavaScript
Sphinx
Objective-C
爬虫
NoSQL
Kubernetes
MySQL
OpenResty
PHP
HTML
热门文章
Redis、MemCache、MongoDB比较
macOS常用命令
OpenResty+Lua+Kafka收集日志
Nginx常用配置说明
Elasticsearch详解
Supervisor使用总结
Docker使用总结
Git使用总结
CentOS常用命令总结
Qt实现TCP通讯