Qt實(shí)現(xiàn)簡(jiǎn)單的TCP通信
這段時(shí)間用到了QT的TCP通信,做了初步的學(xué)習(xí)與嘗試,編寫(xiě)了一個(gè)客戶(hù)端和服務(wù)器基于窗口通信的小例程。
使用QT的網(wǎng)絡(luò)套接字需要.pro文件中加入一句:
QT += network
一、客戶(hù)端
1、客戶(hù)端的代碼比服務(wù)器稍簡(jiǎn)單,總的來(lái)說(shuō),使用QT中的QTcpSocket類(lèi)與服務(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、以下是客戶(hù)端的例程
首先是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類(lèi),還需要用到QTcpSever類(lèi)。即便如此,也只是比客戶(hù)端復(fù)雜一點(diǎn)點(diǎn),用到了6個(gè)步驟:
(1)創(chuàng)建QTcpSever對(duì)象
server = new QTcpServer();
(2)偵聽(tīng)一個(gè)端口,使得客戶(hù)端可以使用這個(gè)端口訪(fǎng)問(wèn)服務(wù)器
server->listen(QHostAddress::Any, port);
(3)當(dāng)服務(wù)器被客戶(hù)端訪(fǎng)問(wèn)時(shí),會(huì)發(fā)出newConnection()信號(hào),因此為該信號(hào)添加槽函數(shù),并用一個(gè)QTcpSocket對(duì)象接受客戶(hù)端訪(fǎng)問(wèn)
?connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect); ?? ?void MainWindow::server_New_Connect() ?{ ? ? ?//獲取客戶(hù)端連接 ? ? ?socket = server->nextPendingConnection(); ?}
(4)使用socket的write函數(shù)向客戶(hù)端發(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() ?{ ? ? ?//獲取客戶(hù)端連接 ? ? ?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編寫(xiě)tcp通信工具(Client篇)
- QT網(wǎng)絡(luò)通信TCP客戶(hù)端實(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)文章
OpenGL通過(guò)中點(diǎn)法繪制直線(xiàn)和圓
這篇文章主要為大家詳細(xì)介紹了OpenGL通過(guò)中點(diǎn)法繪制直線(xiàn)和圓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02C語(yǔ)言鏈表實(shí)現(xiàn)歌手評(píng)分系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言鏈表實(shí)現(xiàn)歌手評(píng)分系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03C++實(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-08C++二叉樹(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-10C/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