QT5实现简单的TCP通信
这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。
使用QT的网络套接字需要.pro文件中加入一句:
- QT += network
一、客户端
1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:
(1)创建QTcpSocket套接字对象
- socket = new QTcpSocket();
(2)使用这个对象连接服务器
- socket->connectToHost(IP, port);
(3)使用write函数向服务器发送数据
- socket->write(data);
(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
- QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
- void MainWindow::socket_Read_Data()
- {
- QByteArray buffer;
- //读取缓冲区数据
- buffer = socket->readAll();
- }
(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)
- socket->disconnectFromHost();
2、以下是客户端的例程
首先是mainwindow.h文件:
- //mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QTcpSocket>
- 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文件:
- //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!";
- }
最后是ui的设计:
二、服务器
1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:
(1)创建QTcpSever对象
- server = new QTcpServer();
- server->listen(QHostAddress::Any, port)
(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问
- connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
- void MainWindow::server_New_Connect()
- {
- //获取客户端连接
- socket = server->nextPendingConnection();
- }
(4)使用socket的write函数向客户端发送数据
- socket->write(data);
(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
- QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
- void MainWindow::socket_Read_Data()
- {
- QByteArray buffer;
- //读取缓冲区数据
- buffer = socket->readAll();
- }
(6)取消侦听
- server->close();
2、以下是服务器的例程
首先是mainwindow.h文件:
- //mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QTcpServer>
- #include <QTcpSocket>
- 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文件:
- #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()<<server->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!";
- }
最后是ui的设计:
三、运行结果