網(wǎng)絡(luò)編程有 TCP 和 UDP,TCP 編程需要用到倆個類:QTcpServer 和 QTcpSocket。![]() 1 TCP 實(shí)現(xiàn)服務(wù)器和客戶端 TCP 協(xié)議(Transmission Control Protocol)是一種面向連接的,可靠的,基于字節(jié)流的傳輸層通信協(xié)議,傳輸數(shù)據(jù)穩(wěn)定可靠。 在 help 索引中搜索到如圖 兩個重要類: ![]() 服務(wù)器編程中兩個類都會用到,客戶端編程中只會用到 QTcpSocket 對象。 本實(shí)驗(yàn)中對 QTcpServer 類的基本使用: (1)監(jiān)聽客戶端連接。 (2)每當(dāng)有新的客戶端連接服務(wù)器的時候,會自動觸發(fā)信號, (3)根據(jù)當(dāng)前連接上的新的客戶端創(chuàng)建一個 Socket 對象,將數(shù)據(jù)的收發(fā)動作交給 socket 套 接字去處理。 (4)關(guān)閉服務(wù)器 close(); 對 QTcpSocket 類的基本使用: (1)服務(wù)器端:有新連接時獲取連接狀態(tài),綁定 socket 。 (2)客戶端:通過 socket 連接服務(wù)器,連接成功觸發(fā)信號。. (3)當(dāng)有數(shù)據(jù)到來時會觸發(fā)信號,用 readAll()讀取。 (4)通過讀寫 socket 收發(fā)數(shù)據(jù)。 具體步驟: 步驟一:創(chuàng)建工程,在工程文件.pro 中添加 network,如圖: ![]() 步驟二:設(shè)計 ui 界面, 1. 在屬性編輯欄設(shè)置主窗口大小: ![]() 2. 添加組件 接收窗口: Plain Text Edit 發(fā)送窗口,IP 地址窗口,端口號窗口:Line Edit 打開服務(wù)器,關(guān)閉服務(wù)器:Push Button 拖拽完成后逐個布局,根據(jù)需要設(shè)置組件大小,這里端口號框設(shè)置成了最小 200 ![]() 按鈕布局:拖拽按鈕和彈簧,然后點(diǎn)擊水平布局。 ![]() 然后選中全部組件,點(diǎn)擊柵格布局: ![]() 最后更改組件名稱注釋,完成后如圖 : ![]() 步驟三:服務(wù)器端編程: 1.創(chuàng)建 QTcpServer 對象 2.創(chuàng)建監(jiān)聽端口,使得客戶端可以使用這個端口訪問服務(wù)器,使用 listen 函數(shù)。 bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0); 第一個參數(shù)是綁定指定的地址(即本機(jī)服務(wù)器 IP),第二個參數(shù)是綁定的本服務(wù)器端口號。 監(jiān)聽某個端口時,如果有新連接進(jìn)來就發(fā)出 newConnection()信號。 3.當(dāng)服務(wù)器對象被訪問時,會發(fā)出 newConnection()信號,所以為該信號添加槽函數(shù)并用一個 QTcpSocket對象接受客戶端的訪問。 4.當(dāng)socket接受緩沖區(qū)有新數(shù)據(jù)到來時,會發(fā)出readyRead()信號,為該信號添加槽函數(shù),使用readyRead()讀取。 5.socket 發(fā)送數(shù)據(jù)可直接調(diào)用 write()成員函數(shù)。 6.關(guān)閉端口號。 代碼如下: #include #include #include namespace Ui { class TcpServer; } class TcpServer : public QMainWindow { Q_OBJECT public: explicit TcpServer(QWidget *parent = 0); ~TcpServer(); QTcpServer * tcpServer; QTcpSocket * tcpSocket; public slots: void newConnection_Slot(void); void readyRead_Solt(void); private slots: void on_openBu_clicked(); void on_sendBu_clicked(); void on_closeBu_clicked(); private: Ui::TcpServer *ui; }; #include "tcpserver.h" #include "ui_tcpserver.h" #include #include #include TcpServer::TcpServer(QWidget *parent) : QMainWindow(parent), ui(new Ui::TcpServer) { ui->setupUi(this); tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); //連接信號與槽函數(shù)進(jìn)行綁定 connect(tcpServer,SIGNAL(newConnection()),SLOT(newConnection_Slot())); } //連接信號槽函數(shù) void TcpServer::newConnection_Slot(void) { //連接客戶端后 socket tcpSocket = tcpServer->nextPendingConnection(); //套接字的接收數(shù)據(jù)信號與都數(shù)據(jù)槽函數(shù)連接 connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Solt())); } //讀取數(shù)據(jù) void TcpServer::readyRead_Solt(void) { QString buf; //讀取 buf = tcpSocket->readAll(); ui->recvEdit->appendPlainText(buf); } TcpServer::~TcpServer() { delete ui; } //打開 void TcpServer: ![]() { //監(jiān)聽 tcpServer->listen(QHostAddress::Any,ui->portEdit->text().toUInt()); } //發(fā)送數(shù)據(jù) void TcpServer: ![]() { tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); } //關(guān)閉 void TcpServer: ![]() { tcpSocket->close(); } 步驟四:客戶端編程 ![]() 1.創(chuàng)建 QTcpSocket 套接字對象 2.使用套接字對象的成員函數(shù)去請求連接服務(wù)器。 void connectToHost(const QHostAddress &address, quint16 port, openMode mode = ReadWrite); 第一個參數(shù)為服務(wù)器 IP 地址,第二個參數(shù)為服務(wù)器端口號。第三個參數(shù)為打開方式,默認(rèn)為可讀可寫 函數(shù)功能:請求連接服務(wù)器連接成功后發(fā)出connected()信號,綁定槽函數(shù)connected_Solt()去操作socket。 3.使用 write 函數(shù)向服務(wù)器發(fā)送數(shù)據(jù),當(dāng) socket 接收緩沖區(qū)有新數(shù)據(jù)到來時 會發(fā)出 readyRead()信號,為該信號添加槽函數(shù)以讀取數(shù)據(jù)。 4.斷開與服務(wù)器的連接。 class TcpClient : public QMainWindow { ....... private slots: void on_openBt_clicked(); void connected_Solt(void); void readyRead_Solt(void); void on_sendEdit_2_clicked(); void on_closeBt_clicked(); }; TcpClient::TcpClient(QWidget *parent) : QMainWindow(parent), ui(new Ui::TcpClient) { ui->setupUi(this); //創(chuàng)建 socket 對象 tcpSocket = new QTcpSocket(this); } TcpClient::~TcpClient() { delete ui; } //打開(連接服務(wù)器) void TcpClient: ![]() { tcpSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toUInt()); connect(tcpSocket,SIGNAL(connected()),this,SLOT(connected_Solt())); } //等待數(shù)據(jù)到來 void TcpClient::connected_Solt(void) { connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Solt())); } //讀取數(shù)據(jù) void TcpClient::readyRead_Solt(void) { ui->recvEdit->appendPlainText(tcpSocket->readAll()); } //發(fā)送 void TcpClient: ![]() { tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); } //關(guān)閉 void TcpClient: ![]() { tcpSocket->close(); } 編譯運(yùn)行成功,使用服務(wù)器和客戶端通信如圖: ![]() ![]() |