Qt實(shí)現(xiàn)TCP網(wǎng)絡(luò)編程
本文實(shí)例為大家分享了Qt實(shí)現(xiàn)TCP網(wǎng)絡(luò)編程的具體代碼,供大家參考,具體內(nèi)容如下
1.Qt中的TCP客戶端編程
Qt中的TCP客戶端編程:
對(duì)于Qt編程而言,網(wǎng)絡(luò)只是數(shù)據(jù)傳輸?shù)耐ǖ?/strong>
Qt提供了QTcpSocket類(封裝了TCP協(xié)議細(xì)節(jié))
將QTcpSocket的對(duì)象當(dāng)做黑盒使用,進(jìn)行數(shù)據(jù)收發(fā)
QTcpSocket的使用方式:
1.連接服務(wù)端主機(jī)(connectToHost())
2.發(fā)送數(shù)據(jù)/接受數(shù)據(jù)(write()/read())
3.關(guān)閉連接(close())
QTcpSocket的注意事項(xiàng):
默認(rèn)情況下,QTcpSocket使用異步編程的方式:
操作完成后立即返回
通過(guò)發(fā)送信號(hào)的方式返回操作結(jié)果
QTcpSocket提供了輔助函數(shù),可完成同步編程的方式
waitForConnected()/waitForDisconnected()
waitForBytesWritten()/waitForReadyread()
QTcpSocket的同步編程:
編程實(shí)驗(yàn):同步編程
#include <QCoreApplication> #include <QTcpSocket> #include <QDebug> #include <QThread> void SyncClientDemo() { ? ? QTcpSocket client; ? ? char buf[256] = {0}; ? ? client.connectToHost("127.0.0.1",8080); ? ? qDebug() << "Connected:" << client.waitForConnected(); ? ? qDebug() << "Send Bytes:" << client.write("CKY"); ? ? qDebug() << "Send Status:" << client.waitForBytesWritten(); ? ? qDebug() << "Data Avilable:" << client.waitForReadyRead(); ? ? qDebug() << "Received Bytes:" << client.read(buf, sizeof(buf)); ? ? qDebug() << "Received Data:" << buf; ? ? QThread::sleep(5000); ? ? client.close(); ? ? client.waitForDisconnected(); } int main(int argc, char *argv[]) { ? ? QCoreApplication a(argc, argv); ? ? SyncClientDemo(); ? ? return a.exec(); }
QTcpSocket的異步編程:
QTcpSocket對(duì)象通過(guò)發(fā)送信號(hào)的方式返回操作結(jié)果
可以在程序中將對(duì)應(yīng)的信號(hào)連接到槽函數(shù),獲取結(jié)果
在GUI應(yīng)用程序中通常使用QTcpSocket的異步方式
QTcpSocket中的關(guān)鍵信號(hào):
connected():成功連接遠(yuǎn)端主機(jī)
disconnected():遠(yuǎn)端主機(jī)斷開(kāi)連接
readyRead():遠(yuǎn)程數(shù)據(jù)到達(dá)本機(jī)
bytesWritten(qint64):數(shù)據(jù)成功發(fā)送至系統(tǒng)(OS)
編程實(shí)驗(yàn):QTcpSocket異步編程
#include "clientdemo.h" #include <QDebug> #include <QHostAddress> ClientDemo::ClientDemo(QObject* parent) : QObject(parent) { ? ? connect(&m_client, SIGNAL(connected()), this, SLOT(onConnected())); ? ? connect(&m_client, SIGNAL(disconnected()), this, SLOT(onDisconnected())); ? ? connect(&m_client, SIGNAL(readyRead()), this, SLOT(onDataReady())); ? ? connect(&m_client, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64))); } void ClientDemo::onConnected() { ? ? qDebug() << "onConnected()"; ? ? qDebug() << "Local Address:" << m_client.localAddress(); ? ? qDebug() << "Loacl Port:" << m_client.localPort(); } void ClientDemo::onDisconnected() { ? ? qDebug() << "onDiecennected()"; } void ClientDemo::onDataReady() { ? ? char buf[256] = {0}; ? ? qDebug() << "onDataReady:" << m_client.read(buf, sizeof(buf)); ? ? qDebug() << "Data:" << buf; } void ClientDemo::onBytesWritten(qint64 bytes) { ? ? qDebug() << "onBytesWritten" << bytes; } void ClientDemo::connectTo(QString ip, int port) { ? ? m_client.connectToHost(ip, port); } qint64 ClientDemo::send(const char* data, int len) { ? ? return m_client.write(data, len); } qint64 ClientDemo::available() { ? ? return m_client.bytesAvailable(); } void ClientDemo::close() { ? ? m_client.close(); }
1.Qt中的TCP服務(wù)端編程
網(wǎng)絡(luò)中的服務(wù)端:
服務(wù)端是為客戶端服務(wù)的,服務(wù)的內(nèi)容諸如向客戶端提供資源,保存客戶端數(shù)據(jù),為客戶端提供功能接口,等
Client/Server軟件架構(gòu)簡(jiǎn)介
特點(diǎn);
服務(wù)端被動(dòng)接受連接(服務(wù)端無(wú)法主動(dòng)連接客戶端)
服務(wù)端必須公開(kāi)網(wǎng)絡(luò)地址(容易受到攻擊)
在職責(zé)上:
客戶端傾向于處理用于交互及體驗(yàn)(GUI)
服務(wù)端傾向于用戶數(shù)據(jù)的組織和存儲(chǔ)(數(shù)據(jù)處理)
B/S網(wǎng)絡(luò)結(jié)構(gòu)是什么?
Browser/Server軟件架構(gòu)簡(jiǎn)介
B/S是一種特殊的C/S網(wǎng)絡(luò)架構(gòu)
B/S中的客戶端統(tǒng)一使用瀏覽器(Browser)
B/S中的客戶端GUI通常采用HTML進(jìn)行開(kāi)發(fā)
B/S中的客戶端與服務(wù)端通常采用http協(xié)議進(jìn)行通信
Qt中的TCP服務(wù)端編程:
Qt提供了QTcpServer類
將QTcpServer的對(duì)象當(dāng)做黑盒使用,進(jìn)行連接監(jiān)聽(tīng)
每一個(gè)連接生成一個(gè)QTcpSocket對(duì)象進(jìn)行通信
QTcpServer的使用方式:
監(jiān)聽(tīng)本機(jī)地址的端口(listen())
通過(guò)信號(hào)通知客戶端連接(newConnection())
獲取QTcpSocket通信對(duì)象(nextPendingConnection())
停止監(jiān)聽(tīng)(close())
QTcpServer的注意事項(xiàng):
用于處理客戶端連接,不進(jìn)行具體通信
監(jiān)聽(tīng)的端口只用于響應(yīng)連接請(qǐng)求
監(jiān)聽(tīng)到連接后,生成QTcpSocket對(duì)象與客戶端通信
Client/Server交互流程:
編程實(shí)驗(yàn):QServerSocket編程
#include "serverdemo.h" #include "QHostAddress" #include <QDebug> #include <QTcpServer> #include <QObjectList> ServerDemo::ServerDemo(QObject* parent) : QObject(parent) { ? ? connect(&m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection())); } void ServerDemo::onNewConnection() { ? ? qDebug() << "onNewConnection"; ? ? QTcpSocket* tcp = m_server.nextPendingConnection(); ? ? connect(tcp, SIGNAL(connected()), this, SLOT(onConnected())); ? ? connect(tcp, SIGNAL(disconnected()), this, SLOT(onDisconnected())); ? ? connect(tcp, SIGNAL(readyRead()), this, SLOT(onDataReady())); ? ? connect(tcp, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64))); } bool ServerDemo::start(int port) { ? ? bool ret = true; ? ? if(!m_server.isListening()) ? ? { ? ? ? ? ret = m_server.listen(QHostAddress("127.0.0.1", port)); ? ? } ? ? return ret; } void ServerDemo::stop() { ? ? if(m_server.isListening()) ? ? { ? ? ? ? m_server.close(); ? ? } } void ServerDemo::onConnected() { ? ? QTcpServer* tcp = dynamic_cast<QTcpServer*>(sender()); ? ? if(tcp != NULL) ? ? { ? ? ? ? qDebug() << "onConnected()"; ? ? ? ? qDebug() << "Local Address:" << tcp->localAddress(); ? ? ? ? qDebug() << "Loacl Port:" << tcp->localPort(); ? ? } } void ServerDemo::onDisconnected() { ? ? qDebug() << "onDiecennected()"; } void ServerDemo::onDataReady() { ? ? QTcpServer* tcp = dynamic_cast<QTcpServer*>(sender()); ? ? char buf[256] = {0}; ? ? if(tcp != NULL) ? ? { ? ? ? ? qDebug() << "onDataReady:" << tcp->read(buf, sizeof(buf)); ? ? ? ? qDebug() << "Data:" << buf; ? ? } } void ServerDemo::onBytesWritten(qint64 bytes) { ? ? qDebug() << "onBytesWritten" << bytes; } ServerDemo::~ServerDemo() { ? ? const QObjectList& list = m_server.children(); ? ? for(int i = 0; i < list.length(), i++) ? ? { ? ? ? ? QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(list[i]); ? ? ? ? if(tcp != NULL) ? ? ? ? { ? ? ? ? ? ? tcp->close(); ? ? ? ? } ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c語(yǔ)言實(shí)現(xiàn)向上取整計(jì)算方法
這篇文章主要介紹了c語(yǔ)言實(shí)現(xiàn)向上取整計(jì)算方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07C語(yǔ)言函數(shù)聲明以及函數(shù)原型超詳細(xì)講解示例
這篇文章主要介紹了C語(yǔ)言函數(shù)聲明以及函數(shù)原型超詳細(xì)講解,C語(yǔ)言代碼由上到下依次執(zhí)行,原則上函數(shù)定義要出現(xiàn)在函數(shù)調(diào)用之前,否則就會(huì)報(bào)錯(cuò)。但在實(shí)際開(kāi)發(fā)中,經(jīng)常會(huì)在函數(shù)定義之前使用它們,這個(gè)時(shí)候就需要提前聲明2023-02-02C++ accumulate函數(shù)詳細(xì)介紹和具體案例
這篇文章主要介紹了C++ accumulate函數(shù)詳細(xì)介紹和具體案例,accumulate是numeric庫(kù)中的一個(gè)函數(shù),主要用來(lái)對(duì)指定范圍內(nèi)元素求和,但也自行指定一些其他操作,如范圍內(nèi)所有元素相乘、相除等2022-08-08C++ Boost Random隨機(jī)函數(shù)詳解
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-11-11C++字符串和數(shù)字的去重操作和鞍點(diǎn)的尋找
大家好,本篇文章主要講的是C++字符串和數(shù)字的去重操作和鞍點(diǎn)的尋找,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12C++進(jìn)程共享數(shù)據(jù)封裝成類實(shí)例
這篇文章主要介紹了C++進(jìn)程共享數(shù)據(jù)封裝成類的方法,以實(shí)例形式講述了其封裝代碼與具體用法,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10VC++6.0實(shí)現(xiàn)直線掃描轉(zhuǎn)換的圖文教程
這篇文章主要給大家介紹了關(guān)于VC++6.0實(shí)現(xiàn)直線掃描轉(zhuǎn)換的相關(guān)資料,文中通過(guò)圖文將實(shí)現(xiàn)的步驟一步步介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用VC++6.0具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-01-01