<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                本系列所有文章可以在這里查看[http://blog.csdn.net/cloud_castle/article/category/2123873](http://blog.csdn.net/cloud_castle/article/category/2123873) 上篇博文談到了QTcpSocket基于線程的同步網絡客戶端的實現,主要基于Waitfor...()函數。如果用多線程做服務器怎么做呢,不要緊,官網依然有Demo~ 這個例子共有7個文件(不算pro,如果例子的pro文件很特別我會挑出來討論下),部分實現與Fortune Server相同,就不重復說了。 主要是多實現了一個FortuneServer類繼承自QTcpServer,為什么要寫這樣一個類呢?因為服務器要響應多個Client的請求, 你不能把所有Client請求的數據都寫到Dialog里面吧,一是使主界面只關注GUI的實現,二也是為了復用性嘛~ 例子介紹: The Threaded Fortune Server example shows how to create a server for a simple network service that uses threads to handle requests from different clients. main.cpp: ~~~ #include <QApplication> #include <QtCore> #include <stdlib.h> // 使用隨機函數包含的頭文件 #include "dialog.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Dialog dialog; dialog.show(); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); // 隨機種子初始化 return app.exec(); } ~~~ fortuneserver.h: ~~~ #ifndef FORTUNESERVER_H #define FORTUNESERVER_H #include <QStringList> #include <QTcpServer> //! [0] class FortuneServer : public QTcpServer { Q_OBJECT public: FortuneServer(QObject *parent = 0); protected: void incomingConnection(qintptr socketDescriptor); // 第(1)點 private: QStringList fortunes; }; //! [0] #endif ~~~ 第一點,FortuneServer類重新實現了QTcpSocket類的incomingConnection(qintptr socketDescriptor)函數,這是個虛函數,保證了基類指針調用子類方法。qintptr是平臺相關的整型,可以理解為在64位系統下 typedef qintptr qint64,在32位系統下typedef qintptr qint32。但是FortuneThread類中socketDescription參數卻是int型的,為什么?因為FortuneServer類是由外部調用的,這個參數也是從外部讀進來的,因此需要屏蔽系統間的差別。FortuneThread類的socketDescription是由FortuneServer給進來的,同一個平臺,直接int就好了。 socketDescription是套接字的描述符,作為每個Client端的識別碼。 fortuneserver.cpp: ~~~ #include "fortuneserver.h" #include "fortunethread.h" #include <stdlib.h> //! [0] FortuneServer::FortuneServer(QObject *parent) : QTcpServer(parent) { fortunes << tr("You've been leading a dog's life. Stay off the furniture.") // 在構造函數中將fortunes初始化 << tr("You've got to think about tomorrow.") << tr("You will be surprised by a loud noise.") << tr("You will feel hungry again in another hour.") << tr("You might have mail.") << tr("You cannot kill time without injuring eternity.") << tr("Computers are not intelligent. They only think they are."); } //! [0] //! [1] void FortuneServer::incomingConnection(qintptr socketDescriptor) // socketDescriptor作為參數從外部接收,因此用qintptr修飾 { QString fortune = fortunes.at(qrand() % fortunes.size()); // qrand() % n表示在[0,n-1]取一個隨機數 FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this); // 以此socketDescription初始化FortuneThread connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); // 線程完成后刪除自身的信號槽綁定 thread->start(); // 啟動線程 } //! [1] ~~~ FortuneServer類就完成了,incomingconnection()是protected的虛函數,不能直接由QTcpSocket的對象調用的~ 來看fortunethread線程類是怎么寫的。fortunethread.h: ~~~ #ifndef FORTUNETHREAD_H #define FORTUNETHREAD_H #include <QThread> #include <QTcpSocket> //! [0] class FortuneThread : public QThread { Q_OBJECT public: FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent); void run(); // 繼承QThread重寫run()幾乎是必須的 signals: void error(QTcpSocket::SocketError socketError); // 自定義信號方便其他線程的特定事件處理 private: int socketDescriptor; QString text; }; //! [0] #endif ~~~ fortunethread.cpp: ~~~ #include "fortunethread.h" #include <QtNetwork> //! [0] FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent) : QThread(parent), socketDescriptor(socketDescriptor), text(fortune) // 利用初始化列表對成員變量賦值 { } //! [0] //! [1] void FortuneThread::run() { QTcpSocket tcpSocket; // run()函數中創建的棧對象保證了可靠的銷毀。注意這個變量的依附性,當前線程變量僅在調用它的線程中有效。 //! [1] //! [2] if (!tcpSocket.setSocketDescriptor(socketDescriptor)) { // 相當于tcpSocket的初始化,參數是為了保證不會為同一個客戶端創建多個QTcpSocket對象 emit error(tcpSocket.error()); return; } //! [2] //! [3] QByteArray block; // 參見Fortune Server QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); out << (quint16)0; out << text; out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16)); //! [3] //! [4] tcpSocket.write(block); tcpSocket.disconnectFromHost(); // 這個函數是異步執行的 tcpSocket.waitForDisconnected(); // 注意到這又是個waitFor...()函數,它會阻塞當前線程直到連接斷開 } //! [4] ~~~ dialog.h: ~~~ #ifndef DIALOG_H #define DIALOG_H #include <QWidget> #include "fortuneserver.h" QT_BEGIN_NAMESPACE class QLabel; class QPushButton; QT_END_NAMESPACE class Dialog : public QWidget { Q_OBJECT public: Dialog(QWidget *parent = 0); private: QLabel *statusLabel; QPushButton *quitButton; FortuneServer server; // 比較一下,與Blocking Fortune Client里的FortuneThread成員的優勢 }; #endif ~~~ dialog.cpp: ~~~ #include <QtWidgets> #include <QtNetwork> #include <stdlib.h> #include "dialog.h" #include "fortuneserver.h" Dialog::Dialog(QWidget *parent) : QWidget(parent) { statusLabel = new QLabel; statusLabel->setWordWrap(true); quitButton = new QPushButton(tr("Quit")); quitButton->setAutoDefault(false); if (!server.listen()) { // 打開子線程,只用了這一句話 QMessageBox::critical(this, tr("Threaded Fortune Server"), tr("Unable to start the server: %1.") .arg(server.errorString())); close(); return; } QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 address for (int i = 0; i < ipAddressesList.size(); ++i) { if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } } // if we did not find one, use IPv4 localhost if (ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.") .arg(ipAddress).arg(server.serverPort())); connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); buttonLayout->addStretch(1); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(statusLabel); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setWindowTitle(tr("Threaded Fortune Server")); } ~~~ Fortune財富例程相關大概就是這些,回頭做個總結。今天太累啦~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看