QT TCP多線程網絡通信

學習目標:?TCP網絡通信編程

學習前置環境

運行環境:qt?creator 4.12

QT TCP網絡通信編程-CSDN博客

Qt 線程 QThread類詳解-CSDN博客

學習內容

使用多線程技術實現服務端計數器

?核心代碼

客戶端

客戶端:負責連接服務端,每次連接次數+1。以及連接的報錯信息

#include "dialog.h"
#include "ui_dialog.h"
#include<QDebug>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);ui->server_ip->setText("127.0.0.1");ui->server_port->setText("8888");clientSocket =new QTcpSocket;setWindowTitle("連接計數器客戶端");//連接錯誤回調QObject::connect(clientSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, [this](QAbstractSocket::SocketError error){switch (error) {case QAbstractSocket::RemoteHostClosedError: // 遠程主機關閉連接// QMessageBox::information(this, "提示", "遠程主機關閉連接", QMessageBox::Yes);break;case QAbstractSocket::HostNotFoundError: // 找不到主機地址QMessageBox::information(this, "提示", "找不到主機地址", QMessageBox::Yes);break;case QAbstractSocket::ConnectionRefusedError: // 連接被對方拒絕(或者超時)QMessageBox::information(this, "提示", "連接被對方拒絕(或者超時)", QMessageBox::Yes);break;default:QMessageBox::information(this, "提示", tr("致命錯誤為:").arg(clientSocket->errorString()), QMessageBox::Yes);}ui->request->setEnabled(true);ui->close->setEnabled(true);});//當 socket 成功連接到服務器時,會發射 connected() 信號。connect(clientSocket,&QTcpSocket::connected,this,[this](){QString str ="已經連接到服務器端\n服務器端ip:"+clientSocket->peerAddress().toString()+"服務器端port:"+QString::number(clientSocket->peerPort());//QMessageBox::information(this, "提示",str , QMessageBox::Yes);ui->request->setEnabled(false);ui->close->setEnabled(true);QString msg=ui->currentv->text()+'\n';clientSocket->write(msg.toUtf8(),msg.length());int count =(ui->currentv->text().toUInt());ui->currentv->setNum(++count);});//當 socket 與服務器斷開連接時,會發射 disconnected() 信號。connect(clientSocket,&QTcpSocket::disconnected,this,[this](){QString str ="已斷開與服務器端的連接\n服務器端ip:"+clientSocket->peerAddress().toString()+"服務器端port:"+QString::number(clientSocket->peerPort());//QMessageBox::information(this, "提示",str , QMessageBox::Yes);clientSocket->close();});ui->request->setEnabled(true);ui->close->setEnabled(true);}Dialog::~Dialog()
{delete ui;
}void Dialog::on_request_clicked()
{clientSocket->connectToHost(ui->server_ip->text(),ui->server_port->text().toInt());}void Dialog::on_close_clicked()
{clientSocket->close(); // 取消已有的連接  后續觸發斷開回調ui->request->setEnabled(true);ui->close->setEnabled(false);
}

服務端

新連接請求類

通過繼承重寫的方式,實現新連接的回調操作。當然你也可以使用信號槽機制。如

connect(tcpServer, &QTcpServer::newConnection,對象,行為)。

實現功能:交給線程池處理,綁定實現連接斷開前,把公用計數器+1操作,釋放并清理資源。可以理解為綁定亡語操作,死后(連接斷開)觸發。

#ifndef TCPNEWCONNET_H
#define TCPNEWCONNET_H#include"writethread.h"
#include"dialog.h"class Dialog;class TcpNewConnet : public QTcpServer  //基于重寫虛函數 實現新連接回調函數
{
Q_OBJECT
public:TcpNewConnet()=default;~TcpNewConnet()=default;TcpNewConnet(QObject *parent=0):QTcpServer(parent){dlgs =(Dialog*)parent;}
protected:// 當有新連接的時候會自動調用此函數void TcpNewConnet::incomingConnection(qintptr socketdescriptor){WriteThread *thread=new WriteThread(socketdescriptor,0);// 此處用于處理對話框顯示統計訪問次數信息connect(thread,&QThread::finished,dlgs,&Dialog::slotsdispFunc);connect(thread,&QThread::finished,thread,&QThread::deleteLater);thread->start(); // 通過執行這條語句來調用run()函數
}Dialog *dlgs;
};#endif // TCPNEWCONNET_H

多線程類

依然是通過重寫的方式,注意點是Tcpsocket的生命周期,當過了{}作用域會自動釋放這條連接。實現了客戶端連接成功,再釋放。

功能:創造一個連接,然后等這個連接死亡。觸發亡語操作。

#include "writethread.h"WriteThread::WriteThread(int socketdescriptor,QObject *parent):QThread(parent),socketdescriptor(socketdescriptor)
{}void WriteThread::run(){ //多線程執行的函數//QTcpSocket* tcp =new QTcpSocket;    持久化連接{QTcpSocket tcp2; //離開作用域自動釋放這條新連接QTcpSocket* tcp =& tcp2;if(!tcp->setSocketDescriptor(socketdescriptor)){emit myerror(tcp->error());  //觸發自定義的error信號return;}qDebug()<<"run()";QByteArray data;QDataStream out(&data,QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_5_12);tcp->write(data);}//tcp->disconnectFromHost(); //主動斷開與遠程主機的TCP連接。
}

主邏輯類

主要實現按鈕開啟和關閉服務器

#include "dialog.h"
#include "ui_dialog.h"
#include<QMessageBox>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);setWindowTitle("連接計數器服務端");ui->server_ip->setText("127.0.0.1");ui->server_port->setText("8888");icount= 0;tcpserver=new TcpNewConnet(this);}Dialog::~Dialog()
{delete ui;
}void Dialog::slotsdispFunc(){ui->currentv->setText(tr("客戶端請求%1次").arg(++icount));
}void Dialog::on_close_clicked()
{//先關閉所有socketif(!tcpserver){tcpserver->disconnect(); //用于斷開 QTcpSocket 對象的所有信號與槽的連接。tcpserver->close();      //它會向對端發送 FIN 數據包,并等待對端的確認,完成 TCP 連接的正常關閉過程。//fin回調 已調用 tcpSocket->deleteLater(); //它不會立即刪除對象,而是將其標記為待刪除狀態,等到當前事件循環結束后再執行刪除操作。}if(tcpserver->isListening()){tcpserver->close();//不調用 deleteLater 為了下次再次開啟ui->listen->setEnabled(true);ui->close->setEnabled(false);QMessageBox::critical(this,tr("提示"),tr("多線程服務器已關閉"));}}void Dialog::on_listen_clicked()
{QString ip(ui->server_ip->text());uint16_t port =ui->server_port->text().toUInt();if(!tcpserver->listen(QHostAddress(ip),port)){tcpserver->close();QMessageBox::critical(this,tr("提示"),tr("多線程服務器已關閉"));return;}QMessageBox::information(this,tr("提示"),tr("多線程服務器已經啟動"));ui->listen->setEnabled(false);ui->close->setEnabled(true);
}

總結

通過繼承重寫和信號槽的方式,可以實現連接建立,斷開,發送前,發送后等等操作綁定,重寫需要去找指定的重寫函數,而信號去找指定的信號名。信號槽機制當綁定多個的時候,是按照綁定的順序執行,因為底層是信號隊列,保證順序。

如果對信號槽有興趣,可以看我之前發布的qt 多線程和網絡編程文章。

最后附上源代碼鏈接
對您有幫助的話,幫忙點個star

?41-clinet-count · jbjnb/Qt demo - 碼云 - 開源中國 (gitee.com)

41-server-count · jbjnb/Qt demo - 碼云 - 開源中國 (gitee.com)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/43088.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/43088.shtml
英文地址,請注明出處:http://en.pswp.cn/web/43088.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從零開始做題:MP3

題目 給出一個mp3文件 解題 右鍵->selection->save selection->另存為xxx.png即可 8750d5109208213f E:\逐鹿\MISC\tools\MP3Stego_1_1_19\MP3Stego>.\decode -X cipher.mp3 MP3StegoEncoder 1.1.19 See README file for copyright info Input file cipher.mp3…

未來代理IP的發展趨勢:創新、適應和可持續性

你是否好奇&#xff0c;未來代理IP將如何演變以適應日益復雜和全球化的網絡環境&#xff1f;讓我們探討一下代理IP技術在創新、適應性和可持續發展方面的未來前景。 1. 創新技術驅動 未來的代理IP將依托創新技術&#xff0c;如邊緣計算、區塊鏈和深度學習。邊緣計算技術的應用…

AcWing 5458:進水排水問題

【題目描述】 某已經蓄滿水的泳池內裝有 4 個水管。 前 2 個水管是進水管&#xff0c;單位時間的進水量分別為 a,b。 后 2 個水管是排水管&#xff0c;單位時間的排水量分別為 c,d。 請你計算&#xff0c;當 4 個水管同時工作時&#xff0c;是否可能將泳池里的水排干。【輸入格…

53-5 內網代理7 - CS上線不出網主機

靶場搭建: 這里就用之前內網代理的靶場,把web服務器這臺虛擬機關閉掉,用剩下的3臺加kali 各個虛擬機的網絡情況 kali - 可以連接外網win2008(之前的FTP服務器) 可以連接外網 win 7(之前的辦公電腦) 不出網主機 - 無法連接外網win2012 克隆機(之前的域控) - 無法連接…

視頻壓縮文件太大了怎么縮小?3個壓縮方法分享

視頻壓縮文件太大了怎么縮小&#xff1f;當視頻壓縮文件過大時&#xff0c;縮小其大小不僅能節省寶貴的存儲空間&#xff0c;還能顯著提升文件傳輸速度&#xff0c;特別是在網絡條件有限的情況下。通過專業的視頻壓縮軟件&#xff0c;可以有效減少文件體積&#xff0c;使視頻內…

python庫(9):prettytable庫快速實現ASCII表格

下面介紹一個快速制作ASCII表格庫——prettytable&#xff0c;可以方便地制作簡單表格。 1 安裝prettytable pip install -i https://pypi.tuna.tsinghua.edu.cn/simple prettytable 結果如下&#xff1a; 2 代碼實例 from prettytable import PrettyTable table PrettyTa…

【Python系列】深入解析 Python 中的 JSON 處理工具

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

兼容MySQL和PostgreSQL協議的數據庫

兼容MySQL和PostgreSQL協議的數據庫 一、Aurora二、TDSQL數據庫三、TDSQL-C數據庫四、TDSQL-C MySQL 版和 TDSQL MySQL 版的區別 一、Aurora Aurora是由亞馬遜網絡服務&#xff08;AWS&#xff09;提供的一種關系型數據庫引擎。它是在MySQL和PostgreSQL之上構建的&#xff0c;…

coco數據集格式計算mAP的python腳本

目錄 背景說明COCOeval 計算mAPtxt文件轉換為coco json 格式自定義數據集標注 背景說明 在完成YOLOv5模型移植&#xff0c;運行在板端后&#xff0c;通常需要衡量板端運行的mAP。 一般需要兩個步驟 步驟一&#xff1a;在板端批量運行得到目標檢測結果&#xff0c;可保存為yol…

【Django項目】基于Python+Django+MySQL的音樂網站系統項目

功能介紹 首頁&#xff1a;歌曲分類、歌曲搜索、熱門歌曲、熱門下載、新歌推薦 歌曲排行&#xff1a;歌曲分類、分頁功能 用戶板塊&#xff1a;用戶登陸/注冊、播放歷史 歌曲詳情&#xff1a;歌曲播放、當前播放列表、歌曲點評、歌曲播放插件、下載歌曲 系統后臺&#xff1a;歌…

MySQL體系架構解析

1.MySQL體系架構 1.1.MySQL的分支與變種 MySQL變種有好幾個,主要有三個久經考驗的主流變種:Percona Server,MariaDB和 Drizzle。它們都有活躍的用戶社區和一些商業支持,均由獨立的服務供應商支持。同時還有幾個優秀的開源關系數據庫,值得我們了解一下。 1.1.1.Drizzle …

【Sql Server修改列類型錯誤信息:對象名依賴于列】

Sql Server修改列類型錯誤信息&#xff1a;對象名依賴于列 報錯信息解決方法測試sql語句 報錯信息 修改表中列類型&#xff0c;發生報錯如下&#xff1a; [SQL Server]對象DF__Forecast___isCal__4E746892 依賴于 列isCalcFinished。 (5074) [42000] [Microsoft][ODBC Driver…

L2 LangGraph_Components

參考自https://www.deeplearning.ai/short-courses/ai-agents-in-langgraph&#xff0c;以下為代碼的實現。 這里用LangGraph把L1的ReAct_Agent實現&#xff0c;可以看出用LangGraph流程化了很多。 LangGraph Components import os from dotenv import load_dotenv, find_do…

2024年高壓電工證考試題庫及高壓電工試題解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2024年高壓電工證考試題庫及高壓電工試題解析是安全生產模擬考試一點通結合&#xff08;安監局&#xff09;特種作業人員操作證考試大綱和&#xff08;質檢局&#xff09;特種設備作業人員上崗證考試大綱隨機出的高壓…

uniapp vue3微信小程序如何獲取dom元素

在網上很多人說可以通過下面兩種形式獲取到指定dom元素 // 定義ref <div ref"box"></div>//1通過this.$refs獲取dom元素 this.$refs.box//2通過ref(null)獲取dom元素 let box ref(null)第一種方式在vue2中是可以獲取到的&#xff0c;但是在vue3 setup中…

開源項目有哪些機遇與挑戰

目錄 1.概述 2.開源項目的發展趨勢 2.1. 開源項目的發展現狀 2.2. 開源社區的活躍度 2.3. 開源項目在技術創新中的作用 3.參與開源的經驗分享 3.1. 選擇開源項目 3.2. 理解項目結構和文檔 3.3. 貢獻代碼 3.4. 與開源社區的合作 3.5. 學習和成長 4.開源項目的挑戰 …

內褲洗衣機到底值不值得買?五大高質量靠譜內衣洗衣機值得擁有

市場上出現了內衣洗衣機&#xff0c;這種洗衣機比市面上的普通洗衣機的清潔力好&#xff0c;還具有除菌功能&#xff0c;在清洗完內衣褲的過程中&#xff0c;可以將衣物上的細菌去除掉&#xff0c;但市面上的內衣品牌眾多&#xff0c;什么樣的牌子才好用呢&#xff1f;作為一位…

前端簡歷:如何寫項目經歷(經驗)找出細節點和重難點,輕松應對面試?

&#xff08;下面內容&#xff1a;我將結合我的實際項目帶大家進行每一步驟的梳理&#xff09; 項目經歷-堂食外送點餐 2022年2月-2022年5月 項目描述&#xff1a;該平臺提供外送訂餐服務&#xff0c;用戶可以在手機中輕松地瀏覽菜品、下單、支付、編輯地址、填寫個人信息等…

手擼俄羅斯方塊——游戲設計

手擼俄羅斯方塊——游戲設計 概述 上一章我們介紹俄羅斯方塊的基本信息&#xff0c;包括坐標點和方塊的基本概念&#xff0c;這一章節我們繼續介紹如何完成后續的游戲設計。 組成游戲的基本要素 俄羅斯方塊作為一個 2D 的平面游戲&#xff0c;我們可以將整個參與元素做如下…

簡過網:工程專業最吃香的6個證書,你考了幾個了?

工程專業最吃香的6個證書&#xff0c;你考了幾個了&#xff1f;我們一起來看看吧&#xff01; 1、二級建造師 報考條件&#xff1a;工程類大專及以上學歷/從事相關職業 考試時間&#xff1a;3月報名、6月考試 就業前景&#xff1a;建筑設計院、房產開發公司、施工單位 2、一…