網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
本文實(shí)例為大家分享了QT編寫(xiě)tcp通信工具的具體實(shí)現(xiàn)代碼,Client篇,供大家參考,具體內(nèi)容如下
1.說(shuō)明
使用qt寫(xiě)一個(gè)類(lèi)似網(wǎng)上常見(jiàn)的網(wǎng)絡(luò)調(diào)試工具。此篇為Client端。下一遍再寫(xiě)Server端。
2.基本流程
Client端相對(duì)簡(jiǎn)單:創(chuàng)建QTcpSocket對(duì)象,為對(duì)象的readyRead,error,connected(可選)分別寫(xiě)槽函數(shù),以處理讀數(shù)據(jù),錯(cuò)誤,連接成功三個(gè)事件。
連接使用對(duì)象的connectToHost方法,斷開(kāi)使用disconnectFromHost方法。
程序不做編碼轉(zhuǎn)換處理,因?yàn)橹暗膸妆槲淖忠呀?jīng)做過(guò),不再贅述。
3.代碼
這是mainwindow.cpp文件。
#include "mainwindow.h"
#include "ui_mainwindow.h"
?
MainWindow::MainWindow(QWidget *parent) :
? ? QMainWindow(parent),
? ? ui(new Ui::MainWindow)
{
? ? ui->setupUi(this);
? ? ui->splitter->setStretchFactor(0,2);
? ? ui->splitter->setStretchFactor(1,1);
?
? ? QString ip=getLocalip();
? ? if( ip.isEmpty() )
? ? {
? ? ? ? QMessageBox::about(this,tr("提示"),tr("無(wú)本地IP。") ) ;
? ? }
? ? else{
? ? ? ? ui->ledtIpLocal->setText( ip ); ? //本地IP
? ? }
? ? ui->labHostName->setText(tr("HostName:")+ QHostInfo::localHostName() );
? ? ui->labHostName->adjustSize();
? ? ui->ledtPortServer->setText(tr("8080")); //默認(rèn)
? ? ui->ledtIpServer->setText (ui->ledtIpLocal->text() );
? ? ui->btnOpen->setEnabled(true);
? ? ui->btnSend->setEnabled(false);
? ? //初始化TCP客戶(hù)端
? ? tcpClient = new QTcpSocket(this);
? ? tcpClient->abort();
?
? ? connect(tcpClient, SIGNAL(readyRead()), this, SLOT(slot_readData()) );
? ? connect(tcpClient, SIGNAL(connected()), this, SLOT(slot_connected()) );
? ? connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(slot_error(QAbstractSocket::SocketError)));
}
?
MainWindow::~MainWindow()
{
? ? delete ui;
}
//獲取本地IP
QString MainWindow::getLocalip()
{
? ? QList<QHostAddress> list = QNetworkInterface::allAddresses();
? ? foreach (QHostAddress address, list)
? ? {
? ? ? ? if(address.protocol() == QAbstractSocket::IPv4Protocol)
? ? ? ? {
? ? ? ? ? ? return address.toString();
? ? ? ? }
? ? }
? ? return "";
}
?
//讀取數(shù)據(jù)
void MainWindow::slot_readData()
{
? ? QByteArray buffer = tcpClient->readAll();
? ? if(!buffer.isEmpty())
? ? {
? ? ? ? ui->tedtRecive->appendPlainText( buffer );
? ? }
}
//連接成功,也可以在方法waitForConnected后面處理。
void MainWindow::slot_connected()
{
? ? ui->btnOpen->setText("斷開(kāi)");
? ? ui->btnSend->setEnabled(true);
? ? ui->btnOpen->setEnabled(true);
? ? ui->ledtPortLocal->setText( QString::number(tcpClient->localPort()) );
}
//錯(cuò)誤處理
void ?MainWindow::slot_error(QAbstractSocket::SocketError)
{
? ? tcpClient->disconnectFromHost();
? ? ui->btnOpen->setText(tr("連接"));
? ? ui->btnOpen->setEnabled(true);
? ? QMessageBox::warning(this,
? ? ? ? tr("注意!"),
? ? ? ? tcpClient->errorString(),
? ? ? ? QMessageBox::Ok ,
? ? ? ? QMessageBox::Ok) ;
}
//連接與斷開(kāi)
void MainWindow::on_btnOpen_clicked()
{
? ? if(ui->btnOpen->text() == "斷開(kāi)")
? ? {
? ? ? ? tcpClient->disconnectFromHost();
? ? ? ? if (
? ? ? ? ? ? ? ? tcpClient->state() == QAbstractSocket::UnconnectedState \
? ? ? ? ? ? ? ? ||( ?tcpClient->waitForDisconnected(1000))
? ? ? ? ? ?)
? ? ? ? {
? ? ? ? ? ? ui->btnOpen->setText("連接");
? ? ? ? ? ? ui->btnSend->setEnabled(false);
? ? ? ? }
? ? }else{
? ? ? ? if( ?ui->ledtPortServer->text().toInt() ==0 ){
? ? ? ? ? ? QMessageBox::about(this,tr("提示"),tr("請(qǐng)輸入端口號(hào)。") ) ;
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? tcpClient->connectToHost(ui->ledtIpServer->text(), ui->ledtPortServer->text().toInt(),QIODevice::ReadWrite,QAbstractSocket::IPv4Protocol);
? ? ? ? ui->btnOpen->setEnabled(false);
? ? ? ? if( !tcpClient->waitForConnected(4000) ) //只等待4秒
? ? ? ? {
? ? ? ? ? ? tcpClient->disconnectFromHost();
? ? ? ? ? ? ui->btnOpen->setText(tr("連接"));
? ? ? ? ? ? ui->btnOpen->setEnabled(true);
? ? ? ? ? ? QMessageBox::warning(this,
? ? ? ? ? ? ? ? tr("注意!"),
? ? ? ? ? ? ? ? tcpClient->errorString(),
? ? ? ? ? ? ? ? QMessageBox::Ok ,
? ? ? ? ? ? ? ? QMessageBox::Ok) ;
? ? ? ? }
? ? }
}
//發(fā)送
void MainWindow::on_btnSend_clicked()
{
? ? if( ?ui->tedtSend->toPlainText().isEmpty() ){
? ? ? ? QMessageBox::about(this,
? ? ? ? tr("提示"),
? ? ? ? tr("請(qǐng)輸入發(fā)送數(shù)據(jù)。")
? ? ? ?) ;
? ? ? ?return;
? ? }
?
? ? tcpClient ->write( ui->tedtSend->toPlainText().toUtf8() );
}
4.附加修改
使用中發(fā)現(xiàn)qt文本框?qū)剀?chē)鍵按“\n”處理,即使是從其他地方粘貼進(jìn)來(lái)也會(huì)自動(dòng)將“\r\n”轉(zhuǎn)為“\n”,這有時(shí)非常不方便,比如測(cè)試wifi模塊的AT命令,還有一些固定格式的網(wǎng)絡(luò)請(qǐng)求。
先對(duì)界面進(jìn)行修改,添加一些功能物件:
這里對(duì)發(fā)送數(shù)據(jù)進(jìn)行處理:
//發(fā)送
void MainWindow::on_btnSend_clicked()
{
?
? ? if( ?ui->tedtSend->toPlainText().isEmpty() ){
? ? ? ? QMessageBox::about(this,
? ? ? ? tr("提示"),
? ? ? ? tr("請(qǐng)輸入發(fā)送數(shù)據(jù)。")
? ? ? ?) ;
? ? ? ?return;
? ? }
? ? QString str = ui->tedtSend->toPlainText() ;
? ? if( ui->checkBox2->isChecked() )
? ? {
? ? ? ? ?str.replace(tr("\n"),tr("\r\n"));
? ? ? ? ?str.replace(tr("\n\n"),tr("\n"));
? ? }
? ? if( ui->checkBox1->isChecked() )str.append(tr("\r\n"));
? ? tcpClient ->write( str.toUtf8() );
}
//計(jì)算字節(jié)數(shù)
void MainWindow::on_btnCalc_clicked()
{
? ? QString str = ui->tedtSend->toPlainText() ;
? ? int len1= str.toUtf8().length();
? ? if( ui->checkBox2->isChecked() )
? ? {
? ? ? ? ?str.replace(tr("\n"),tr("\r\n"));
? ? ? ? ?str.replace(tr("\n\n"),tr("\n"));
? ? }
? ? if( ui->checkBox1->isChecked() )str.append(tr("\r\n"));
?
? ?int len2= str.toUtf8().length();
? ? QMessageBox::about(this,
? ? tr("字節(jié):"),
? ? tr("處理前:")+QString::number (len1,10)+tr(",處理后:")+ QString::number (len2,10)
? ?) ;
}
為了更加方便使用,添加記憶功能,保持上次的填寫(xiě)的內(nèi)容:
//讀取ini文件對(duì)應(yīng)信息
void MainWindow:: readIni(QString key, QString&value)
{
? ? QString path = "save.ini";
? ? //創(chuàng)建文件
? ? QSettings *config = new QSettings(path, QSettings::IniFormat);
? ? //讀取信息
? ? QVariant variant = config->value(QString("info/") + key);
? ? value = variant.value<QString>();
? ? delete config;
}
?
//寫(xiě)入ini文件對(duì)應(yīng)信息
void MainWindow::writeIni(QString key, QString value)
{
? ? QString path = "save.ini";
? ? //創(chuàng)建文件
? ? QSettings *config = new QSettings(path, QSettings::IniFormat);
? ? QVariant variant;
? ? variant.setValue(value);
? ? //信息寫(xiě)入文件
? ? config->beginGroup("info");
? ? config->setValue(key, variant);
? ? config->endGroup();
? ? delete config;
}
原文鏈接:https://blog.csdn.net/wangzibigan/article/details/121409668
相關(guān)推薦
- 2022-12-24 Kubernetes?Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請(qǐng)求解析_云和虛擬化
- 2022-11-24 PyTorch?Dataset與DataLoader使用超詳細(xì)講解_python
- 2022-10-07 C語(yǔ)言一個(gè)函數(shù)如何實(shí)現(xiàn)好幾個(gè)return返回值_C 語(yǔ)言
- 2022-10-16 python?IO多路復(fù)用之epoll詳解_python
- 2022-12-09 Python網(wǎng)絡(luò)編程之Python編寫(xiě)TCP協(xié)議程序的步驟_python
- 2022-05-11 使用kettle的數(shù)據(jù)庫(kù)增量備份與全量備份
- 2022-04-19 C#多線程系列之多線程鎖lock和Monitor_C#教程
- 2022-05-25 <C++>搞明白構(gòu)造函數(shù)和析構(gòu)函數(shù)有這一篇就夠了
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支