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