QT編寫tcp通信工具(Client篇)
本文實例為大家分享了QT編寫tcp通信工具的具體實現(xiàn)代碼,Client篇,供大家參考,具體內(nèi)容如下
1.說明
使用qt寫一個類似網(wǎng)上常見的網(wǎng)絡調(diào)試工具。此篇為Client端。下一遍再寫Server端。
2.基本流程
Client端相對簡單:創(chuàng)建QTcpSocket對象,為對象的readyRead,error,connected(可選)分別寫槽函數(shù),以處理讀數(shù)據(jù),錯誤,連接成功三個事件。
連接使用對象的connectToHost方法,斷開使用disconnectFromHost方法。
程序不做編碼轉換處理,因為之前的幾遍文字已經(jīng)做過,不再贅述。
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("無本地IP。") ) ; ? ? } ? ? else{ ? ? ? ? ui->ledtIpLocal->setText( ip ); ? //本地IP ? ? } ? ? ui->labHostName->setText(tr("HostName:")+ QHostInfo::localHostName() ); ? ? ui->labHostName->adjustSize(); ? ? ui->ledtPortServer->setText(tr("8080")); //默認 ? ? ui->ledtIpServer->setText (ui->ledtIpLocal->text() ); ? ? ui->btnOpen->setEnabled(true); ? ? ui->btnSend->setEnabled(false); ? ? //初始化TCP客戶端 ? ? 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("斷開"); ? ? ui->btnSend->setEnabled(true); ? ? ui->btnOpen->setEnabled(true); ? ? ui->ledtPortLocal->setText( QString::number(tcpClient->localPort()) ); } //錯誤處理 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) ; } //連接與斷開 void MainWindow::on_btnOpen_clicked() { ? ? if(ui->btnOpen->text() == "斷開") ? ? { ? ? ? ? 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("請輸入端口號。") ) ; ? ? ? ? ? ? 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("請輸入發(fā)送數(shù)據(jù)。") ? ? ? ?) ; ? ? ? ?return; ? ? } ? ? ? tcpClient ->write( ui->tedtSend->toPlainText().toUtf8() ); }
4.附加修改
使用中發(fā)現(xiàn)qt文本框?qū)剀囨I按“\n”處理,即使是從其他地方粘貼進來也會自動將“\r\n”轉為“\n”,這有時非常不方便,比如測試wifi模塊的AT命令,還有一些固定格式的網(wǎng)絡請求。
先對界面進行修改,添加一些功能物件:
這里對發(fā)送數(shù)據(jù)進行處理:
//發(fā)送 void MainWindow::on_btnSend_clicked() { ? ? ? if( ?ui->tedtSend->toPlainText().isEmpty() ){ ? ? ? ? QMessageBox::about(this, ? ? ? ? tr("提示"), ? ? ? ? tr("請輸入發(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() ); } //計算字節(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) ? ?) ; }
為了更加方便使用,添加記憶功能,保持上次的填寫的內(nèi)容:
//讀取ini文件對應信息 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; } ? //寫入ini文件對應信息 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); ? ? //信息寫入文件 ? ? config->beginGroup("info"); ? ? config->setValue(key, variant); ? ? config->endGroup(); ? ? delete config; }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Cocos2d-x UI開發(fā)之CCControlPotentiometer控件類使用實例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlPotentiometer控件類使用實例,本文代碼中包含注釋來講解CCControlPotentiometer控件類的使用,需要的朋友可以參考下2014-09-09