Qt實(shí)現(xiàn)簡(jiǎn)單的TCP通信
這段時(shí)間用到了QT的TCP通信,做了初步的學(xué)習(xí)與嘗試,編寫了一個(gè)客戶端和服務(wù)器基于窗口通信的小例程。
使用QT的網(wǎng)絡(luò)套接字需要.pro文件中加入一句:
QT += network
一、客戶端
1、客戶端的代碼比服務(wù)器稍簡(jiǎn)單,總的來(lái)說(shuō),使用QT中的QTcpSocket類與服務(wù)器進(jìn)行通信只需要以下5步:
(1)創(chuàng)建QTcpSocket套接字對(duì)象
socket = new QTcpSocket();
(2)使用這個(gè)對(duì)象連接服務(wù)器
socket->connectToHost(IP, port);
(3)使用write函數(shù)向服務(wù)器發(fā)送數(shù)據(jù)
socket->write(data);
(4)當(dāng)socket接收緩沖區(qū)有新數(shù)據(jù)到來(lái)時(shí),會(huì)發(fā)出readRead()信號(hào),因此為該信號(hào)添加槽函數(shù)以讀取數(shù)據(jù)
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
??
?void MainWindow::socket_Read_Data()
?{
? ? ?QByteArray buffer;
? ? ?//讀取緩沖區(qū)數(shù)據(jù)
? ? ?buffer = socket->readAll();
?}(5)斷開(kāi)與服務(wù)器的連接(關(guān)于close()和disconnectFromHost()的區(qū)別,可以按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();
??
? ? ?//連接信號(hào)槽
? ? ?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();
? ? ? ? ?//獲取端口號(hào)
? ? ? ? ?port = ui->lineEdit_Port->text().toInt();
??
? ? ? ? ?//取消已有的連接
? ? ? ? ?socket->abort();
? ? ? ? ?//連接服務(wù)器
? ? ? ? ?socket->connectToHost(IP, port);
??
? ? ? ? ?//等待連接成功
? ? ? ? ?if(!socket->waitForConnected(30000))
? ? ? ? ?{
? ? ? ? ? ? ?qDebug() << "Connection failed!";
? ? ? ? ? ? ?return;
? ? ? ? ?}
? ? ? ? ?qDebug() << "Connect successfully!";
??
? ? ? ? ?//發(fā)送按鍵使能
? ? ? ? ?ui->pushButton_Send->setEnabled(true);
? ? ? ? ?//修改按鍵文字
? ? ? ? ?ui->pushButton_Connect->setText("斷開(kāi)連接");
? ? ?}
? ? ?else
? ? ?{
? ? ? ? ?//斷開(kāi)連接
? ? ? ? ?socket->disconnectFromHost();
? ? ? ? ?//修改按鍵文字
? ? ? ? ?ui->pushButton_Connect->setText("連接");
? ? ? ? ?ui->pushButton_Send->setEnabled(false);
? ? ?}
?}
??
?void MainWindow::on_pushButton_Send_clicked()
?{
? ? ?qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
? ? ? //獲取文本框內(nèi)容并以ASCII碼形式發(fā)送
? ? ?socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? ?socket->flush();
?}
??
?void MainWindow::socket_Read_Data()
?{
? ? ?QByteArray buffer;
? ? ?//讀取緩沖區(qū)數(shù)據(jù)
? ? ?buffer = socket->readAll();
? ? ?if(!buffer.isEmpty())
? ? ?{
? ? ? ? ?QString str = ui->textEdit_Recv->toPlainText();
? ? ? ? ?str+=tr(buffer);
? ? ? ? ?//刷新顯示
? ? ? ? ?ui->textEdit_Recv->setText(str);
? ? ?}
?}
??
?void MainWindow::socket_Disconnected()
?{
? ? ?//發(fā)送按鍵失能
? ? ?ui->pushButton_Send->setEnabled(false);
? ? ?//修改按鍵文字
? ? ?ui->pushButton_Connect->setText("連接");
? ? ?qDebug() << "Disconnected!";
?}最后是ui的設(shè)計(jì):

二、服務(wù)器
1、服務(wù)器除了使用到了QTcpSocket類,還需要用到QTcpSever類。即便如此,也只是比客戶端復(fù)雜一點(diǎn)點(diǎn),用到了6個(gè)步驟:
(1)創(chuàng)建QTcpSever對(duì)象
server = new QTcpServer();
(2)偵聽(tīng)一個(gè)端口,使得客戶端可以使用這個(gè)端口訪問(wèn)服務(wù)器
server->listen(QHostAddress::Any, port);
(3)當(dāng)服務(wù)器被客戶端訪問(wèn)時(shí),會(huì)發(fā)出newConnection()信號(hào),因此為該信號(hào)添加槽函數(shù),并用一個(gè)QTcpSocket對(duì)象接受客戶端訪問(wèn)
?connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
??
?void MainWindow::server_New_Connect()
?{
? ? ?//獲取客戶端連接
? ? ?socket = server->nextPendingConnection();
?}(4)使用socket的write函數(shù)向客戶端發(fā)送數(shù)據(jù)
socket->write(data);
(5)當(dāng)socket接收緩沖區(qū)有新數(shù)據(jù)到來(lái)時(shí),會(huì)發(fā)出readRead()信號(hào),因此為該信號(hào)添加槽函數(shù)以讀取數(shù)據(jù)
?QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
??
?void MainWindow::socket_Read_Data()
?{
? ? ?QByteArray buffer;
? ? ?//讀取緩沖區(qū)數(shù)據(jù)
? ? ?buffer = socket->readAll();
?}(6)取消偵聽(tīng)
server->close();
2、以下是服務(wù)器的例程
首先是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();
??
? ? ?//連接信號(hào)槽
? ? ?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("偵聽(tīng)"))
? ? ?{
? ? ? ? ?//從輸入框獲取端口號(hào)
? ? ? ? ?int port = ui->lineEdit_Port->text().toInt();
??
? ? ? ? ?//監(jiān)聽(tīng)指定的端口
? ? ? ? ?if(!server->listen(QHostAddress::Any, port))
? ? ? ? ?{
? ? ? ? ? ? ?//若出錯(cuò),則輸出錯(cuò)誤信息
? ? ? ? ? ? ?qDebug()<<server->errorString();
? ? ? ? ? ? ?return;
? ? ? ? ?}
? ? ? ? ?//修改按鍵文字
? ? ? ? ?ui->pushButton_Listen->setText("取消偵聽(tīng)");
? ? ? ? ?qDebug()<< "Listen succeessfully!";
? ? ?}
? ? ?else
? ? ?{
?/*
? ? ? ? ?//如果正在連接(點(diǎn)擊偵聽(tīng)后立即取消偵聽(tīng),若socket沒(méi)有指定對(duì)象會(huì)有異常,應(yīng)修正——2017.9.30)
? ? ? ? ?if(socket->state() == QAbstractSocket::ConnectedState)
? ? ? ? ?{
? ? ? ? ? ? ?//關(guān)閉連接
? ? ? ? ? ? ?socket->disconnectFromHost();
? ? ? ? ?}
?*/
? ? ? ? ?socket->abort();
? ? ? ? ?//取消偵聽(tīng)
? ? ? ? ?server->close();
? ? ? ? ?//修改按鍵文字
? ? ? ? ?ui->pushButton_Listen->setText("偵聽(tīng)");
? ? ? ? ?//發(fā)送按鍵失能
? ? ? ? ?ui->pushButton_Send->setEnabled(false);
? ? ?}
??
?}
??
?void MainWindow::on_pushButton_Send_clicked()
?{
? ? ?qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
? ? ?//獲取文本框內(nèi)容并以ASCII碼形式發(fā)送
? ? ?socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? ?socket->flush();
?}
??
?void MainWindow::server_New_Connect()
?{
? ? ?//獲取客戶端連接
? ? ?socket = server->nextPendingConnection();
? ? ?//連接QTcpSocket的信號(hào)槽,以讀取新數(shù)據(jù)
? ? ?QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
? ? ?QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
? ? ?//發(fā)送按鍵使能
? ? ?ui->pushButton_Send->setEnabled(true);
??
? ? ?qDebug() << "A Client connect!";
?}
??
?void MainWindow::socket_Read_Data()
?{
? ? ?QByteArray buffer;
? ? ?//讀取緩沖區(qū)數(shù)據(jù)
? ? ?buffer = socket->readAll();
? ? ?if(!buffer.isEmpty())
? ? ?{
? ? ? ? ?QString str = ui->textEdit_Recv->toPlainText();
? ? ? ? ?str+=tr(buffer);
? ? ? ? ?//刷新顯示
? ? ? ? ?ui->textEdit_Recv->setText(str);
? ? ?}
?}
??
?void MainWindow::socket_Disconnected()
?{
? ? ?//發(fā)送按鍵失能
? ? ?ui->pushButton_Send->setEnabled(false);
? ? ?qDebug() << "Disconnected!";
?}最后是ui的設(shè)計(jì):

三、運(yùn)行結(jié)果

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Qt中TCP協(xié)議通信詳解
- QT實(shí)現(xiàn)簡(jiǎn)單TCP通信
- QT編寫tcp通信工具(Client篇)
- QT網(wǎng)絡(luò)通信TCP客戶端實(shí)現(xiàn)詳解
- Qt?TCP網(wǎng)絡(luò)通信學(xué)習(xí)
- Qt網(wǎng)絡(luò)編程實(shí)現(xiàn)TCP通信
- QT5實(shí)現(xiàn)簡(jiǎn)單的TCP通信的實(shí)現(xiàn)
- 基于QT的TCP通信服務(wù)的實(shí)現(xiàn)
- QT網(wǎng)絡(luò)編程Tcp下C/S架構(gòu)的即時(shí)通信實(shí)例
- Qt TCP實(shí)現(xiàn)簡(jiǎn)單通信功能
相關(guān)文章
C語(yǔ)言鏈表實(shí)現(xiàn)歌手評(píng)分系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言鏈表實(shí)現(xiàn)歌手評(píng)分系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
C++實(shí)現(xiàn)LeetCode(199.二叉樹(shù)的右側(cè)視圖)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(199.二叉樹(shù)的右側(cè)視圖),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
C++二叉樹(shù)結(jié)構(gòu)的建立與基本操作
二叉樹(shù)是數(shù)據(jù)結(jié)構(gòu)中的樹(shù)的一種特殊情況,有關(guān)二叉樹(shù)的相關(guān)概念,這里不再贅述,如果不了解二叉樹(shù)相關(guān)概念,建議先學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)中的二叉樹(shù)的知識(shí)點(diǎn)2013-10-10
C/C++實(shí)現(xiàn)個(gè)人收支系統(tǒng)的示例代碼
這篇文章主要介紹了C/C++實(shí)現(xiàn)個(gè)人收支系統(tǒng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
本篇文章是對(duì)在c語(yǔ)言中用棧實(shí)現(xiàn)表達(dá)式求值的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

