QTsocket网络编程
目錄
1、開發(fā)工具:VS + QT
1.1 引用網(wǎng)絡(luò)模塊
1.1.1 QT的引用如下:
1.1.2 VS引用如下:
2、編寫服務(wù)器(QTCPServer)?
2.1 準(zhǔn)備工作/連接工作
2.2 發(fā)送或者接受信息
3、編寫客戶端(QTcpSocket)
3.1 準(zhǔn)備工作/連接工作
3.2 發(fā)送或者接受數(shù)據(jù)?
4、編寫過(guò)程中遇到的問(wèn)題
4.1 中文亂碼問(wèn)題
4.2 socket傳輸為空值問(wèn)題
5、運(yùn)用socket進(jìn)行業(yè)務(wù)處理
5.1 客戶端代碼
5.1.1 客戶端向服務(wù)器發(fā)送業(yè)務(wù)
5.1.2 客戶端接受服務(wù)器回應(yīng)
5.2 服務(wù)器代碼
1、開發(fā)工具:VS + QT
使用VS或者使用QT本身的代碼編輯器其實(shí)是一樣的。只是引用QT的網(wǎng)絡(luò)模塊的時(shí)候會(huì)有一些區(qū)別。
1.1 引用網(wǎng)絡(luò)模塊
1.1.1 QT的引用如下:
在qmake項(xiàng)目文件中添加:
QT += network1.1.2 VS引用如下:
右鍵點(diǎn)擊該VS項(xiàng)目,選擇QT
?點(diǎn)擊QT Project Settings,
在General的屬性列中找到QT Modules,
點(diǎn)擊下拉框找到Select Moudles并點(diǎn)擊,然后勾選Network即可。
2、編寫服務(wù)器(QTCPServer)?
2.1 準(zhǔn)備工作/連接工作
首先先引入對(duì)應(yīng)的庫(kù)文件
#include <qtcpserver.h> #include <qtcpsocket.h>在頭文件中創(chuàng)建QTcpServer和QTcpSocket的全局變量
QTcpServer* server; // 服務(wù)器對(duì)象 QTcpSocket* socket;//與客戶端進(jìn)行發(fā)送接受信息對(duì)象在構(gòu)造器中實(shí)例化server對(duì)象并且開始監(jiān)聽客戶端傳來(lái)的socket對(duì)象信息?
server = new QTcpServer(this);//創(chuàng)建一個(gè)服務(wù)器對(duì)象 server->listen(QHostAddress::Any, 8080); //開始監(jiān)聽網(wǎng)絡(luò)地址以及端口號(hào)2.2 發(fā)送或者接受信息
//當(dāng)server檢測(cè)到有socket申請(qǐng)連接并且連接成功的時(shí)候,會(huì)發(fā)出newConnection信號(hào)并且執(zhí)行下面的邏輯 connect(server, &QTcpServer::newConnection, this, [=]() {socket = server->nextPendingConnection(); //得到一個(gè)用于通信的套接字對(duì)象//往客戶段中發(fā)送信息socket->write("server");//socket的write方法其實(shí)是有幾個(gè)重載方法的,如果為了方便,可以直接用QString類型的變量作為參數(shù)。//當(dāng)有數(shù)據(jù)可以接受,socket對(duì)象發(fā)出信號(hào)readyReadconnect(socket, &QTcpSocket::readyRead, this, [=](){QString data = socket->readAll();//讀取客戶端傳來(lái)的數(shù)據(jù)qDebug() << "客戶端傳來(lái)的數(shù)據(jù)" << data;//將數(shù)據(jù)寫到客戶端中});//斷開連接connect(socket, &QTcpSocket::disconnected, this, [=](){socket->close();socket->deleteLater();//釋放指向的內(nèi)存qDebug() << "結(jié)束服務(wù)器";});});//server對(duì)象檢測(cè)到有socket對(duì)象申請(qǐng)連接的時(shí)候,會(huì)調(diào)用listenNews方法3、編寫客戶端(QTcpSocket)
3.1 準(zhǔn)備工作/連接工作
首先引入對(duì)應(yīng)的庫(kù)文件
#include <qtcpsocket.h> #include <qhostaddress.h>在頭文件中創(chuàng)建全局變量QTcpSocket
QTcpSocket* socket;?在構(gòu)造器中實(shí)例化socket對(duì)象并且建立連接
socket = new QTcpSocket(this);//實(shí)例化一個(gè)socket對(duì)象 socket->connectToHost(QHostAddress("127.0.0.1"), 8080); //可以通過(guò)cmd命令窗口輸入命令ipconfig進(jìn)行查看服務(wù)器電腦的ip(或者你知道服務(wù)器的ip也可以)。如果是在本機(jī)運(yùn)行,則IP地址可以輸入默認(rèn)127.0.0.13.2 發(fā)送或者接受數(shù)據(jù)?
//當(dāng)socket發(fā)送有內(nèi)容可讀的信號(hào)的時(shí)候,實(shí)現(xiàn)以下槽函數(shù)(在該函數(shù)接受socket對(duì)象的內(nèi)容)connect(socket, &QTcpSocket::readyRead, this, [=](){QString messageServer = socket->readAll();//接受服務(wù)器傳來(lái)的內(nèi)容qDebug() << messageServer;//將數(shù)據(jù)寫到服務(wù)器中socket->write("我是客戶端");//socket的write方法其實(shí)是有幾個(gè)重載方法的,如果為了方便,可以直接用QString類型的變量作為參數(shù)。});//當(dāng)socket發(fā)送斷開連接信號(hào)的時(shí)候,實(shí)現(xiàn)以下槽函數(shù)connect(socket, &QTcpSocket::disconnected, this, [=](){//socket->close();qDebug() << "斷開連接";//ui.talk->append("斷開連接");//socket->deleteLater();//釋放指向的內(nèi)存});//當(dāng)socket發(fā)送連接成功信號(hào)的時(shí)候,實(shí)現(xiàn)以下槽函數(shù)connect(socket, &QTcpSocket::connected, this, [=](){qDebug() << "連接成功";});至此,簡(jiǎn)單的一個(gè)QTsocket通信就已經(jīng)實(shí)現(xiàn),讀者在運(yùn)用的時(shí)候注意發(fā)送以及接受信息的邏輯即可。?
4、編寫過(guò)程中遇到的問(wèn)題
4.1 中文亂碼問(wèn)題
1、可以在頭文件中加入該代碼
#pragma execution_character_set("utf-8")2、可以用QString自帶的方法
QString::fromLocal8Bit("在這添加你的中文")?4.2 socket傳輸為空值問(wèn)題
這個(gè)問(wèn)題是我在開發(fā)一個(gè)項(xiàng)目的時(shí)候遇到,當(dāng)時(shí)我的情況是在主窗口A先建立與服務(wù)器的連接,然后又打開了一個(gè)新窗口B,在B窗口中又建立了與服務(wù)器的連接,結(jié)果使用完B窗口的socket之后,返回到窗口A,發(fā)現(xiàn)窗口A的socket的write函數(shù)將要傳輸?shù)膬?nèi)容傳輸?shù)椒?wù)器中變成空值。
解決方法:其實(shí)也很簡(jiǎn)單,在每一次建立新的socket連接時(shí)候,將舊的socket先關(guān)閉。也就是說(shuō)我要先關(guān)閉A的socket連接,使用socket->close()函數(shù),然后再建立B窗口的socket連接,最后再關(guān)閉B窗口的socket連接。返回到A窗口之后,再重新建立一次新的socket連接。
這樣問(wèn)題就解決了。
除此之外,我還嘗試了將socket對(duì)象設(shè)置為全工程的一個(gè)全局對(duì)象,但是也無(wú)法解決這個(gè)問(wèn)題。
如果運(yùn)用多線程的技術(shù)應(yīng)該也是可以解決這個(gè)問(wèn)題,但有待讀者去檢驗(yàn)。
5、運(yùn)用socket進(jìn)行業(yè)務(wù)處理
在此只說(shuō)明關(guān)于字符串的一些業(yè)務(wù)處理,對(duì)于視頻流或者圖片等,有待讀者自行研究(但其實(shí)也是大同小異)。
以下借助實(shí)現(xiàn)系統(tǒng)賬號(hào)密碼的增刪改查例子來(lái)說(shuō)明:
問(wèn)題一:服務(wù)器怎么知道客戶端正在處理什么業(yè)務(wù)?
基本邏輯就是,在客戶端將傳輸給服務(wù)器的字符串上加上分隔符,信息傳輸?shù)椒?wù)器時(shí),服務(wù)器將這些字符串進(jìn)行分割提取,從中拿到業(yè)務(wù)信息、賬號(hào)、密碼等內(nèi)容。
5.1 客戶端代碼
5.1.1 客戶端向服務(wù)器發(fā)送業(yè)務(wù)
代碼中的QString對(duì)象 messageClient 就是用來(lái)存放客戶端業(yè)務(wù)的標(biāo)識(shí)符;“-” 就是用來(lái)識(shí)別的信息分隔符
/**********************如果勾選的是添加按鈕**************************/if (ui.add->isChecked() == true){QString accound = ui.account->text(); //記錄輸入的賬號(hào)QString password = ui.password->text();//記錄輸入的密碼messageClient = "accoundAdd";//客戶端添加賬號(hào)業(yè)務(wù)標(biāo)識(shí)符//先判斷賬號(hào)密碼是否為空if (accound == NULL || password == NULL)//如果為空則發(fā)出警告{QMessageBox::information(this, QString::fromLocal8Bit("添加賬號(hào)"), QString::fromLocal8Bit("賬號(hào)或者密碼不可以為空,請(qǐng)重新輸入"));}else//如果不為空則將數(shù)據(jù)傳輸?shù)椒?wù)器{socket->write(messageClient.toUtf8() + "-" + accound.toUtf8() + "-" + password.toUtf8());//將數(shù)據(jù)傳輸?shù)椒?wù)器中}}/**********************如果勾選的是刪除按鈕**************************/if (ui.delete_2->isChecked() == true){QString accound = ui.account->text();//獲取賬號(hào)文本框的信息QString password = "null";//將密碼置為“空”messageClient = "accoundDelete";//客戶端刪除賬號(hào)業(yè)務(wù)標(biāo)識(shí)符if (accound != NULL)//判斷是否為空{(diào)//如果不為空則將數(shù)據(jù)傳輸?shù)椒?wù)器socket->write(messageClient.toUtf8() + "-" + accound.toUtf8() + "-" + password.toUtf8());//將數(shù)據(jù)傳輸?shù)椒?wù)器中}else{QMessageBox::information(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("賬號(hào)不可以為空"));}}/**********************如果勾選的是修改按鈕**************************/if (ui.change->isChecked() == true){QString accound = ui.account->text(); //記錄管理員輸入的賬號(hào)QString password = ui.newpassword->text();//記錄管理員輸入的密碼messageClient = "accoundChange";//客戶端修改賬號(hào)業(yè)務(wù)標(biāo)識(shí)符//先判斷賬號(hào)密碼是否為空if (accound == NULL || password == NULL){QMessageBox::information(this, QString::fromLocal8Bit("修改密碼"), QString::fromLocal8Bit("賬號(hào)或者新密碼不可以為空,請(qǐng)重新輸入"));}else //賬號(hào)和新密碼都不為空{(diào)socket->write(messageClient.toUtf8() + "-" + accound.toUtf8() + "-" + password.toUtf8());//將數(shù)據(jù)傳輸?shù)椒?wù)器中}}5.1.2 客戶端接受服務(wù)器回應(yīng)
socket = new QTcpSocket(this); socket->connectToHost(QHostAddress("127.0.0.1"), 8080);//當(dāng)socket發(fā)送有內(nèi)容可讀的信號(hào)的時(shí)候,實(shí)現(xiàn)以下槽函數(shù)(在該函數(shù)接受socket對(duì)象的內(nèi)容) connect(socket, &QTcpSocket::readyRead, this, [=](){messageServer = socket->readAll();//接受服務(wù)器發(fā)送的信息qDebug() << messageServer;/******************************查找*********************************/if (QString::localeAwareCompare(messageServer, "SearchSuccess") == 0){QMessageBox::information(this, "", QString::fromLocal8Bit("登錄成功"));socket->close();}if (QString::localeAwareCompare(messageServer, "SearchFail") == 0){QMessageBox::information(this, "", QString::fromLocal8Bit("賬號(hào)與密碼不匹配"));}/******************************添加*********************************/if (QString::localeAwareCompare(messageServer, "addSuccess") == 0){QMessageBox::information(this, QString::fromLocal8Bit("添加賬號(hào)"), QString::fromLocal8Bit("添加成功"));socket->close()}if (QString::localeAwareCompare(messageServer, "addFail") == 0){QMessageBox::information(this, QString::fromLocal8Bit("添加賬號(hào)"), QString::fromLocal8Bit("添加失敗"));}if (QString::localeAwareCompare(messageServer, "accoundRepeat") == 0){QMessageBox::information(this, QString::fromLocal8Bit("添加賬號(hào)"), QString::fromLocal8Bit("該賬戶已經(jīng)存在,請(qǐng)重新輸入"));}/******************************刪除***********************************/if (QString::localeAwareCompare(messageServer, "deleteSuccess") == 0){QMessageBox::information(this, QString::fromLocal8Bit("刪除賬號(hào)"), QString::fromLocal8Bit("刪除成功"));socket->close();}if (QString::localeAwareCompare(messageServer, "deleteFail") == 0){QMessageBox::information(this, QString::fromLocal8Bit("刪除賬號(hào)"), QString::fromLocal8Bit("刪除失敗"));}if (QString::localeAwareCompare(messageServer, "delete-accoundNoFound") == 0){QMessageBox::information(this, QString::fromLocal8Bit("刪除賬號(hào)"), QString::fromLocal8Bit("刪除失敗,賬號(hào)沒(méi)有找到"));}/******************************修改***********************************/if (QString::localeAwareCompare(messageServer, "changeSuccess") == 0){QMessageBox::information(this, QString::fromLocal8Bit("修改賬號(hào)"), QString::fromLocal8Bit("修改成功"));socket->close();}if (QString::localeAwareCompare(messageServer, "changeFail") == 0){QMessageBox::information(this, QString::fromLocal8Bit("修改賬號(hào)"), QString::fromLocal8Bit("修改失敗"));}if (QString::localeAwareCompare(messageServer, "change-accoundNoFound") == 0){QMessageBox::information(this, QString::fromLocal8Bit("修改賬號(hào)"), QString::fromLocal8Bit("修改失敗,賬號(hào)沒(méi)有找到"));}});connect(socket, &QTcpSocket::disconnected, this, [=](){qDebug() << QString::fromLocal8Bit("**斷開連接");//ui.talk->append("斷開連接");//socket->deleteLater();//釋放指向的內(nèi)存});connect(socket, &QTcpSocket::connected, this, [=](){qDebug() << QString::fromLocal8Bit("**連接成功");});5.2 服務(wù)器代碼
QStringList對(duì)象的 list 的第一個(gè)元素即list[0]為客戶端目前要執(zhí)行的業(yè)務(wù)信息,利用字符串匹配就可以在服務(wù)器中處理相關(guān)的信息。
該例子涉及到了一些數(shù)據(jù)庫(kù)語(yǔ)句,讀者可以忽略,并不影響整體的傳輸邏輯。
server = new QTcpServer(this);//創(chuàng)建一個(gè)服務(wù)器對(duì)象 server->listen(QHostAddress::Any, port); //開始監(jiān)聽網(wǎng)絡(luò)地址以及端口號(hào)//當(dāng)連接成功的時(shí)候 connect(server, &QTcpServer::newConnection, this, [=]() {socket = server->nextPendingConnection(); //得到一個(gè)用于通信的套接字對(duì)象 //檢測(cè)是否準(zhǔn)備接受數(shù)據(jù),當(dāng)有數(shù)據(jù)可以接受,則發(fā)出信號(hào) readyReadconnect(socket, &QTcpSocket::readyRead, this, [=](){QString data = socket->readAll();//讀取客戶端傳來(lái)的數(shù)據(jù)qDebug() << "客戶端傳來(lái)的數(shù)據(jù)" << data;QStringList list = data.split("-");//QString字符串分割函數(shù),將業(yè)務(wù)信息、賬號(hào)和密碼等提取出來(lái)//查找,用于登錄過(guò)程if (QString::localeAwareCompare(list[0],"login") == 0){QString username1 = list[1];QString password1 = list[2];qDebug() << "賬號(hào):" << username1;qDebug() << "密碼:" << password1;QSqlQuery sql; // 數(shù)據(jù)庫(kù)對(duì)象QString istrue = QString("select * from user1 where username = '%1' and password = '%2'").arg(username1).arg(password1);sql.exec(istrue);if (sql.next() || (username1 == "admin" && password1 == "admin")){socket->write("SearchSuccess");qDebug() << "查找成功";}else{socket->write("SearchFail");qDebug() << "查找失敗";}}//如果客戶端進(jìn)行添加賬號(hào)業(yè)務(wù)if (QString::localeAwareCompare(list[0], "accoundAdd") == 0){QString accound = list[1];QString password = list[2];qDebug() << messageClient;QSqlQuery sql; // 數(shù)據(jù)庫(kù)對(duì)象//第一步、先查重istrue = QString("select * from user1 where username = '%1'").arg(accound);sql.exec(istrue);if (sql.next()){socket->write("accoundRepeat");//賬號(hào)重復(fù)qDebug() << "賬號(hào)重復(fù)";}else{//如果數(shù)據(jù)庫(kù)沒(méi)有該賬號(hào),則進(jìn)行添加istrue = QString("insert into user1(username,password) values('%1','%2')").arg(accound).arg(password);sql.exec(istrue);//檢查是否插入成功istrue = QString("select * from user1 where username = '%1' and password = '%2'").arg(accound).arg(password);sql.exec(istrue);if (sql.next()){socket->write("addSuccess");qDebug() << "添加成功";}else{socket->write("addFail");qDebug() << "添加失敗";}}}//客戶端進(jìn)行刪除賬號(hào)業(yè)務(wù)if (QString::localeAwareCompare(list[0], "accoundDelete") == 0){QString accound = list[1];QString password = list[2];qDebug() << messageClient;QSqlQuery sql; // 數(shù)據(jù)庫(kù)對(duì)象//想刪除 先查詢istrue = QString("select * from user1 where username = '%1'").arg(accound);sql.exec(istrue);if (sql.next())//如果存在{istrue = QString("delete from user1 where username = '%1'").arg(accound);sql.exec(istrue);//查看是否刪除成功istrue = QString("select * from user1 where username = '%1'").arg(accound);sql.exec(istrue);if (sql.next()){socket->write("deleteFail");qDebug() << "刪除失敗";}else{socket->write("deleteSuccess");qDebug() << "刪除成功";}}else{socket->write("delete-accoundNoFound");qDebug() << "賬號(hào)不存在";}}//客戶端進(jìn)行修改賬號(hào)密碼業(yè)務(wù)if (QString::localeAwareCompare(list[0], "accoundChange") == 0){QString accound = list[1];QString password = list[2];qDebug() << messageClient;QSqlQuery sql; // 數(shù)據(jù)庫(kù)對(duì)象istrue = QString("select * from user1 where username = '%1'").arg(accound);sql.exec(istrue);if (sql.next())//如果存在{istrue = QString("update user1 set password = '%1' where username = '%2'").arg(password).arg(accound);sql.exec(istrue);//查看是否修改成功istrue = QString("select * from user1 where username = '%1' and password = '%2'").arg(accound).arg(password);sql.exec(istrue);if (sql.next()){socket->write("changeSuccess");qDebug() << "修改成功";}else{socket->write("changeFail");qDebug() << "修改失敗";}}else{socket->write("change-accoundNoFound");qDebug() << "賬號(hào)不存在";}}}); });總結(jié)
以上是生活随笔為你收集整理的QTsocket网络编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 微机总线地址,物理地址 ,虚拟地址
- 下一篇: 1.web技术的前世今生