<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C++ Qt開發:QTcpSocket網絡通信組件

      Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹如何運用QTcpSocket組件實現基于TCP的網絡通信功能。

      QTcpSocketQTcpServer是Qt中用于實現基于TCP(Transmission Control Protocol)通信的兩個關鍵類。TCP是一種面向連接的協議,它提供可靠的、雙向的、面向字節流的通信。這兩個類允許Qt應用程序在網絡上建立客戶端和服務器之間的連接。

      以下是QTcpSocket類的一些常用函數:

      函數 描述
      QTcpSocket() 構造函數,創建一個新的QTcpSocket對象。
      ~QTcpSocket() 析構函數,釋放QTcpSocket對象及其資源。
      void connectToHost(const QString &hostName, quint16 port) 嘗試與指定主機名和端口建立連接。
      void disconnectFromHost() 斷開與主機的連接。
      QAbstractSocket::SocketState state() const 返回套接字的當前狀態。
      QHostAddress peerAddress() const 返回與套接字連接的遠程主機的地址。
      quint16 peerPort() const 返回與套接字連接的遠程主機的端口。
      QAbstractSocket::SocketError error() const 返回套接字的當前錯誤代碼。
      qint64 write(const char *data, qint64 maxSize) 將數據寫入套接字,返回實際寫入的字節數。
      qint64 read(char *data, qint64 maxSize) 從套接字讀取數據,返回實際讀取的字節數。
      void readyRead() 當套接字有可供讀取的新數據時發出信號。
      void bytesWritten(qint64 bytes) 當套接字已經寫入指定字節數的數據時發出信號。
      void error(QAbstractSocket::SocketError socketError) 當套接字發生錯誤時發出信號。

      以下是QTcpServer類的一些常用函數及其簡要解釋:

      函數 描述
      QTcpServer() 構造函數,創建一個新的QTcpServer對象。
      ~QTcpServer() 析構函數,釋放QTcpServer對象及其資源。
      bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 開始監聽指定的地址和端口。
      void close() 停止監聽并關閉服務器。
      bool isListening() const 返回服務器是否正在監聽連接。
      QList<QTcpSocket*> pendingConnections() 返回等待處理的掛起連接的列表。
      virtual void incomingConnection(qintptr socketDescriptor) 當有新連接時調用,可以在子類中實現以處理新連接。
      void maxPendingConnections() const 返回允許的最大掛起連接數。
      void setMaxPendingConnections(int numConnections) 設置允許的最大掛起連接數。
      QNetworkProxy proxy() const 返回服務器的代理設置。
      void setProxy(const QNetworkProxy &networkProxy) 設置服務器的代理設置。
      QAbstractSocket::SocketError serverError() const 返回服務器的當前錯誤代碼。
      QString errorString() const 返回服務器的錯誤消息字符串。
      void pauseAccepting() 暫停接受新連接,但保持現有連接。
      void resumeAccepting() 恢復接受新連接。
      void close() 關閉服務器。

      如上這些只是常用函數的簡要描述,詳細的函數說明和用法可以參考Qt官方文檔或相關文檔。

      1.1 通信的流程

      1.1.1 服務端流程

      在使用TCP通信時同樣需要導入Qt+=network模塊,并在頭文件中引入QTcpServerQTcpSocket兩個模塊,當有了模塊的支持,接著就是偵聽套接字,此處可通過調用server.listen來實現偵聽,此函數原型如下;

      bool QTcpServer::listen(
          const QHostAddress &address = QHostAddress::Any, 
          quint16 port = 0
      );
      

      這個函數用于開始在指定的地址和端口上監聽連接。它的參數包括:

      • address:一個QHostAddress對象,指定要監聽的主機地址。默認為QHostAddress::Any,表示監聽所有可用的網絡接口。
      • port:一個quint16類型的端口號,指定要監聽的端口。如果設置為0,系統將選擇一個可用的未使用端口。

      函數返回一個bool值,表示是否成功開始監聽。如果成功返回true,否則返回false,并且可以通過調用errorString()獲取錯誤消息。

      緊隨套接字偵聽其后,通過使用一個waitForNewConnection等待新的連接到達。它的原型如下:

      bool QTcpServer::waitForNewConnection(
          int msec = 0, 
          bool *timedOut = nullptr
      );
      

      該函數在服務器接受新連接之前會一直阻塞。參數包括:

      • msec:等待連接的超時時間(以毫秒為單位)。如果設置為0(默認值),則表示無限期等待,直到有新連接到達。
      • timedOut:一個可選的布爾指針,用于指示等待是否超時。如果傳遞了此參數,并且等待時間達到了指定的超時時間,*timedOut將被設置為true,否則為false。如果不關心超時,可以將此參數設置為nullptr

      函數返回一個布爾值,表示是否成功等待新連接。如果在超時時間內有新連接到達,返回true,否則返回false。如果等待超時,可以通過檢查timedOut參數來確定。如果函數返回false,可以通過調用errorString()獲取錯誤消息。

      套接字的接收會使用nextPendingConnection()函數來實現,nextPendingConnectionQTcpServer 類的成員函數,用于獲取下一個已接受的連接的套接字(QTcpSocket)。它的原型如下:

      QTcpSocket *QTcpServer::nextPendingConnection();
      

      函數返回一個指向新連接套接字的指針。如果沒有已接受的連接,則返回 nullptr

      使用這個函數,你可以在服務器接受連接之后獲取相應的套接字,以便進行數據傳輸和通信。一般來說,在收到 newConnection 信號后,你可以調用這個函數來獲取新連接的套接字。

      當有了套接字以后,就可以通過QTcpServer指針判斷對應的套接字狀態,一般套接字的狀態被定義在QAbstractSocket類內。以下是QAbstractSocket類中定義的一些狀態及其對應的標志:

      狀態標志 描述
      UnconnectedState 未連接狀態,套接字沒有連接到遠程主機。
      HostLookupState 正在查找主機地址狀態,套接字正在解析主機名。
      ConnectingState 連接中狀態,套接字正在嘗試與遠程主機建立連接。
      ConnectedState 已連接狀態,套接字已經成功連接到遠程主機。
      BoundState 已綁定狀態,套接字已經與地址和端口綁定。
      ClosingState 關閉中狀態,套接字正在關閉連接。
      ListeningState 監聽中狀態,用于QTcpServer,表示服務器正在監聽連接。

      這些狀態反映了套接字在不同階段的連接和通信狀態。在實際使用中,可以通過調用state()函數獲取當前套接字的狀態,并根據需要處理相應的狀態。例如,可以使用信號和槽機制來捕獲狀態變化,以便在連接建立或斷開時執行相應的操作。

      當套接字被連接后則可以通過socket->write()方法向上線客戶端發送一個字符串,此處我們以發送lyshark為例,發送時需要向write()中傳入兩個參數。其原型如下:

      qint64 QTcpSocket::write(const char *data, qint64 maxSize);
      

      該函數接受兩個參數:

      • data:指向要寫入套接字的數據的指針。
      • maxSize:要寫入的數據的最大字節數。

      函數返回實際寫入的字節數,如果發生錯誤,則返回 -1。在寫入數據之后,可以使用 bytesWritten 信號來獲取寫入的字節數。此外,你也可以使用 waitForBytesWritten 函數來阻塞等待直到所有數據都被寫入。

      至此服務端代碼可總結為如下案例;

      #include <QCoreApplication>
      #include <QTcpServer>
      #include <QTcpSocket>
      #include <iostream>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          QTcpServer server;
      
          server.listen(QHostAddress::Any,9000);
          server.waitForNewConnection(100000);
      
          QTcpSocket *socket;
      
          socket = server.nextPendingConnection();
          if(socket->state() && QAbstractSocket::ConnectedState)
          {
              QByteArray bytes = QString("lyshark").toUtf8();
              socket->write(bytes.data(),bytes.length());
          }
      
          socket->close();
          server.close();
          return a.exec();
      }
      

      1.1.2 客戶端流程

      客戶端的流程與服務端基本保持一致,唯一的區別在于將server.listen更換為socket.connectToHost連接到對應的主機,QTcpSocketconnectToHost 函數的原型如下:

      void QTcpSocket::connectToHost(
      const QString &hostName, 
      quint16 port, 
      OpenMode openMode = ReadWrite
      );
      
      • hostName:遠程主機的主機名或IP地址。
      • port:要連接的端口號。
      • openMode:套接字的打開模式,默認為 ReadWrite

      函數用于初始化與指定遠程主機和端口的連接。在實際使用中,你可以通過調用這個函數來發起與目標主機的連接嘗試。

      讀取數據時可以使用readAll函數來實現,socket.readAll()QTcpSocket 類的成員函數,用于讀取所有可用的數據并返回一個 QByteArray 對象。其函數函數原型如下:

      QByteArray QTcpSocket::readAll();
      

      該函數返回一個包含從套接字中讀取的所有數據的 QByteArray 對象。通常,你可以通過這個函數來獲取已經到達的所有數據,然后對這些數據進行進一步的處理。其客戶端功能如下所示;

      #include <QCoreApplication>
      #include <QTcpServer>
      #include <QTcpSocket>
      #include <iostream>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          QTcpSocket socket;
          socket.connectToHost(QHostAddress::LocalHost,9000);
      
          if(socket.state() && QAbstractSocket::ConnectedState)
          {
              socket.waitForReadyRead(10000);
      
              QByteArray ref = socket.readAll();
      
              QString ref_string;
      
              ref_string.prepend(ref);
      
              std::cout << ref_string.toStdString() << std::endl;
          }
      
          socket.close();
          return a.exec();
      }
      

      1.2 圖形化應用

      1.2.1 服務端流程

      與命令行版本的網絡通信不同,圖形化部分需要使用信號與槽函數進行綁定,所有的通信流程都是基于信號的,對于服務端而言我們需要導入QTcpServerQtNetworkQTcpSocket模塊,并新增四個槽函數分別對應四個信號;

      信號 槽函數 描述
      connected() onClientConnected() tcpSocket 成功連接到遠程主機時觸發,執行 onClientConnected() 函數。
      disconnected() onClientDisconnected() tcpSocket 斷開連接時觸發,執行 onClientDisconnected() 函數。
      stateChanged(QAbstractSocket::SocketState) onSocketStateChange(QAbstractSocket::SocketState) tcpSocket 的狀態發生變化時觸發,執行 onSocketStateChange() 函數,傳遞新的狀態。
      readyRead() onSocketReadyRead() tcpSocket 有可讀取的新數據時觸發,執行 onSocketReadyRead() 函數。

      在程序入口處我們通過new QTcpServer(this)新建TCP套接字類,并通過connect()連接到初始化槽函數上,當程序運行后會首先觸發newConnection信號,執行onNewConnection槽函數。

      MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      
          // 新建TCP套接字類
          tcpServer=new QTcpServer(this);
      
          // 連接信號初始化其他信號
          connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
      }
      

      而在槽函數onNewConnection中,通過nextPendingConnection新建一個套接字,并綁定其他四個槽函數,這里的槽函數功能各不相同,將其對應的信號綁定到對應槽函數上即可;

      // 初始化信號槽函數
      void MainWindow::onNewConnection()
      {
          // 創建新套接字
          tcpSocket = tcpServer->nextPendingConnection();
      
          // 連接觸發信號
          connect(tcpSocket, SIGNAL(connected()),this, SLOT(onClientConnected()));
          onClientConnected();
      
          // 關閉觸發信號
          connect(tcpSocket, SIGNAL(disconnected()),this, SLOT(onClientDisconnected()));
      
          // 狀態改變觸發信號
          connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
          onSocketStateChange(tcpSocket->state());
      
          // 讀入數據觸發信號
          connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
      }
      

      當讀者點擊偵聽時則直接調用tcpServer->listen實現對本地IP的8888端口的偵聽功能,停止偵聽則是調用tcpServer->close函數實現,如下所示;

      // 開始偵聽
      void MainWindow::on_pushButton_2_clicked()
      {
          // 此處指定綁定本機的8888端口
          tcpServer->listen(QHostAddress::LocalHost,8888);
          ui->plainTextEdit->appendPlainText("[+] 開始監聽");
          ui->plainTextEdit->appendPlainText(" 服務器地址:" + tcpServer->serverAddress().toString() +
                                             " 服務器端口:"+QString::number(tcpServer->serverPort())
                                             );
      }
      
      // 停止偵聽
      void MainWindow::on_pushButton_3_clicked()
      {
          if (tcpServer->isListening())
          {
              tcpServer->close();
          }
      }
      

      對于讀取數據可以通過canReadLine()函數判斷行,并通過tcpClient->readLine()逐行讀入數據,相對應的發送數據可通過調用tcpSocket->write函數實現,在發送之前需要將其轉換為QByteArray類型的字符串格式,如下所示;

      // 讀取數據
      void MainWindow::onSocketReadyRead()
      {
          while(tcpSocket->canReadLine())
              ui->plainTextEdit->appendPlainText("[接收] | " + tcpSocket->readLine());
      }
      
      // 發送數據
      void MainWindow::on_pushButton_clicked()
      {
          QString  msg=ui->lineEdit->text();
          ui->plainTextEdit->appendPlainText("[發送] | " + msg);
      
          QByteArray str=msg.toUtf8();
          str.append('\n');
          tcpSocket->write(str);
      }
      

      運行服務端程序,并點擊偵聽按鈕此時將會在本地的8888端口上啟用偵聽,如下圖所示;

      1.2.2 客戶端流程

      對于客戶端而言同樣需要綁定四個信號并對應到特定的槽函數上,其初始化部分與服務端保持一致,唯一不同的是客戶端使用connectToHost函數鏈接到服務端上,斷開連接時使用的是disconnectFromHost函數,如下所示;

      // 連接服務器時觸發
      void MainWindow::on_pushButton_2_clicked()
      {
          // 連接到8888端口
          tcpClient->connectToHost(QHostAddress::LocalHost,8888);
      }
      
      // 斷開時觸發
      void MainWindow::on_pushButton_3_clicked()
      {
          if (tcpClient->state()==QAbstractSocket::ConnectedState)
              tcpClient->disconnectFromHost();
      }
      

      此處的讀取數據與服務端保持一致,發送數據時則是通過tcpClient->write(str)函數直接傳遞給客戶端,代碼如下所示;

      // 讀取數據時觸發
      void MainWindow::onSocketReadyRead()
      {
          while(tcpClient->canReadLine())
          {
              ui->plainTextEdit->appendPlainText("[接收] | " + tcpClient->readLine());
          }
      }
      
      // 發送消息時觸發
      void MainWindow::on_pushButton_clicked()
      {
          QString msg=ui->lineEdit->text();
          ui->plainTextEdit->appendPlainText("[發送] | " + msg);
          QByteArray str=msg.toUtf8();
          str.append('\n');
          tcpClient->write(str);
      }
      

      運行后,服務端啟用偵聽等待客戶端連接,客戶端連接后,雙方則可以實現數據的收發功能,由于采用了信號機制,兩者的收發并不會阻斷可同時進行,如下圖所示;

      posted @ 2024-03-18 09:25  lyshark  閱讀(3123)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产成人精品亚洲日本片| 麻豆亚州无矿码专区视频| 国产精品福利自产拍在线观看| 99久久精品国产一区二区暴力| 偷拍久久大胆的黄片视频| 精品卡通动漫亚洲AV第一页| 欧美黑吊大战白妞| 神池县| 国产私拍福利精品视频| 济源市| 日本亚洲一区二区精品久久| 天堂av最新版中文在线| 亚洲三区在线观看无套内射| 久久久精品2019中文字幕之3| jizz视频在线观看| 色欲综合久久中文字幕网| 国产精品国产精品偷麻豆| 亚洲天堂在线观看完整版| 欧美成年性h版影视中文字幕| 亚洲国产成人无码av在线影院| 久久天天躁狠狠躁夜夜婷| 自慰无码一区二区三区| 亚洲精品一二三区在线看| 国产亚洲视频免费播放| 当涂县| 国产精品自产在线观看一| 不卡一区二区三区视频播放| 婷婷色爱区综合五月激情韩国| 国产精品免费看久久久无码| 日韩中文字幕人妻一区| 国产口爆吞精在线视频2020版| 国产不卡av一区二区| 屏边| 国产精品美女一区二三区| 中文字幕日韩精品东京热| 欧美人与动牲猛交A欧美精品| 中文字幕午夜福利片午夜福利片97| 狠狠色丁香婷婷综合尤物| 亚洲国产欧美日韩另类| 久久亚洲中文字幕伊人久久大| 国产av午夜精品福利|