• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      基于Qt的線程池服務(wù)器的研究與應(yīng)用

      2014-01-01 03:10:00張衛(wèi)強
      無線電通信技術(shù) 2014年6期
      關(guān)鍵詞:監(jiān)聽線程調(diào)用

      劉 飛,張衛(wèi)強,羅 彤

      (寧波大學信息科學與工程學院,浙江寧波315211)

      0 引言

      傳統(tǒng)的網(wǎng)絡(luò)服務(wù)器模型中,服務(wù)器收到一個客戶端請求后,創(chuàng)建一個新線程,由該線程執(zhí)行任務(wù),任務(wù)完成后,線程退出,即“即時創(chuàng)建,即時刪除”,對服務(wù)器來說創(chuàng)建線程已經(jīng)比創(chuàng)建進程節(jié)約了不少時間,但是如果大量的客戶端對服務(wù)器過于頻繁的進行連接,該服務(wù)器就將在創(chuàng)建和刪除線程的過程中耗費大量時間[1]。所以減少創(chuàng)建和銷毀對象,尤其是減少很耗資源的對象成為提高服務(wù)程序效率的重要手段之一。線程池是一組預先創(chuàng)建的線程,快速、容易地處理收到的業(yè)務(wù)。比起傳統(tǒng)的“即時創(chuàng)建,即時刪除”的模型,該類型服務(wù)器節(jié)省了創(chuàng)建和回收線程的開銷,響應(yīng)更快,效率更高[2]。

      為高圖形用戶界面的響應(yīng)速度,Qt提供豐富的多線程編程支持[],而為減少Q(mào)t創(chuàng)建和刪除線程的開銷,Qt又提供了線程池技術(shù)的支持。為降低基于Qt的網(wǎng)絡(luò)服務(wù)器頻繁的創(chuàng)建線程的開銷,本文就Qt線程池技術(shù)進行分析,研究其運行機制,并運用該技術(shù)創(chuàng)建一個服務(wù)器模型。

      1 Qt的線程池類和QTcpServer類

      Qt提供了與平臺無關(guān)的線程類,在Qt系統(tǒng)中與線程池相關(guān)的最重要的類是QThreadPool和QRunnable。QThreadPool用于管理一批線程,它負責管理和回收單個線程[4]。每個 Qt應(yīng)用可通過QThreadPool::globalInstance()獲得一個全局的QThreadPool對象。QRunable類表示一個任務(wù)或者一段被執(zhí)行代碼的一個接口。使用QThreadPool類來運行一個QRunnable對象。把一個QRunnable放入了QThreadPool的運行隊列中,只要線程是可見的,QRunnable將會被拾起并且在那個線程里運行,QRunnable是一種輕量級的、以“run and forget”方式來在另一個線程開啟任務(wù)的抽象類,為了實現(xiàn)這一功能,要做的全部事情是派生QRunnable類,并實現(xiàn)純虛函數(shù)方法 run()[5]。

      QTcpServer類不是QAbstractSocket抽象套接字類,而是繼承于QObject基類,為編寫TCP客戶端和服務(wù)器應(yīng)用程序提供一個 TCP基礎(chǔ)服務(wù)類[6]。QTcpSocket類提供了基于TCP協(xié)議的通用接口,為監(jiān)聽每一個客戶端的連接,可通過調(diào)用listen()函數(shù)來實現(xiàn),每當服務(wù)器收到一個客戶端的連接請求時就會發(fā)射newConnection()信號,如果要接受待處理的連接,則可通過調(diào)用nextPendingConnection()函數(shù),并返回一個連接的 QTcpSocket()套接字[7],該套接字作為服務(wù)端的一個子對象,可以通過使用這個返回的套接字和客戶端進行連接,這就意味著當QTcpServer對象要銷毀時,該套接字也會隨之被自動刪除,即不能在其他線程中使用該套接字,如果想在其他線程中繼續(xù)使用該套接字,那么需要重載void incomingConnection(int socketDescriptor)函數(shù),這個函數(shù)將新創(chuàng)建一個QTcpSocket套接字,該函數(shù)中socketDescriptor參數(shù)是新連接的套接字描述符,然后在一個整形的待連接鏈表中將套接字存儲,最后發(fā)射信號newConnection()。

      2 線程池機制

      2.1 線程池技術(shù)介紹

      線程池就是在進程中先創(chuàng)建好一批線程,當有任務(wù)到來時,就從創(chuàng)建好的線程中取出一個線程來處理該任務(wù),任務(wù)結(jié)束之后,將線程置為空閑,放回線程池中繼續(xù)等待下次任務(wù)的到來[8],工作過程如圖1所示。

      2.2 基于Qt的線程池機制

      在Qt中通過globalInstance()方法,每個 Qt的應(yīng)用程序都可獲得一個全局的QThreadPool對象。

      theInstance()函數(shù)功能通過Q_GLOBAL_STATIC(QThreadPool,theInstance)宏實現(xiàn),以此返回一個全局的QThreadPool對象。此外由于QThreadPool類繼承QObject,在QThreadPool類中可以使用Qt提供的信號與槽機制。圖1為線程池工作原理。

      圖1 線程池工作原理

      通過上面介紹的函數(shù)就可以得到一個全局的QthreadPool,但是為了能夠調(diào)用該線程池中的一個線程,還需要提供繼承于QRunnable的一個類,從而實現(xiàn)其中的run方法。然后創(chuàng)建一個該類的對象,傳遞給void QThreadPool::Start(QRunnable*runnable,int priority),該函數(shù)具體實現(xiàn)如下所示。

      該方法通過Q_D宏獲取QThreadPool命名為d的數(shù)據(jù)結(jié)構(gòu),真正開始QThreadPool一個線程是通過enqueueTask()方法實現(xiàn)的。

      enqueueTask()方法將runnable放入隊列中來管理,并喚醒QThreadPool管理的線程池中的一個線程實現(xiàn)一個繼承QRunnable類的run方法。

      在默認情況下,QthreadPool將能夠自動刪除創(chuàng)建的 QRunnable對象。使用 void QRunnable::setAutoDelete(bool autoDelete)方法可以改變這一默認行為,但是該標志必須在調(diào)用QThreadPool::Start()之前被設(shè)置,否則將會出現(xiàn)錯誤。

      QThreadPool支持在QRunnable::run方法中通過調(diào)用tryStart(this)來多次執(zhí)行相同的QRunnable。當最后一個線程退出run函數(shù)后,如果autoDelete啟用的話,將刪除QRunnable對象。在autoDelete啟用的情況下,調(diào)用start()方法多次執(zhí)行同一QRunnable會產(chǎn)生競態(tài),因此要避免這樣做。

      通過void setExpiryTimeout(int expiryTimeout)函數(shù)來設(shè)置線程的過期時間,默認過期時間為30 s。如果設(shè)置expriyTimeout為一個負數(shù),則代表禁止使用超時機制。如果要規(guī)定最大的線程數(shù)可通set-MaxThreadCount(int maxThreadCount)來設(shè)置,其參數(shù)maxThreadCount為要設(shè)置的數(shù)量,通過 void maxThreadCount()可以查詢可使用的最大線程數(shù)。為了確保該線程被釋放后可循環(huán)使用,可以通過函數(shù)void releaseThread()釋放該線程的,以便它可以被再次使用。

      3 Qt線程池服務(wù)器模型的建立

      在下面的步驟中,將利用線程池技術(shù)創(chuàng)建一個服務(wù)器模型,以此介紹線程池的創(chuàng)建步驟,并通過命令客戶端對創(chuàng)建的服務(wù)器進行測試。

      3.1 主要相關(guān)代碼

      首先創(chuàng)建一個繼承QTcpServer的一個類,在該類的實現(xiàn)方法中監(jiān)聽客戶端的連接每當有客戶端連接時都會調(diào)用virtual void incomingConnection(int socketDescriptor)函數(shù)[9,10],因此處理這個請求的過程就可以在這個函數(shù)中實現(xiàn),對一個線程池的服務(wù)器,每當客戶端試圖連接的時候,服務(wù)器從線程池中啟動一個線程,負責對這個客戶端進行服務(wù),所以,incomingConnection()這個函數(shù)所要做的就是建立一個線程,進而對客戶端進行服務(wù)。代碼如下,先添加類的前置聲明:

      在myserver.cpp文件中,首先在構(gòu)造函數(shù)中通過globalInstance()函數(shù)獲取一個全局QThreadPool對象,并設(shè)置最大線程數(shù)為20,之后實現(xiàn)監(jiān)聽客戶端連接。

      該服務(wù)器監(jiān)聽到客戶端試圖建立一個套接字連接,該套接字將自動分配一個 SocketDescriptor標識,該標識會在服務(wù)器連接中使用,應(yīng)當提供給每一個線程。

      服務(wù)器在監(jiān)聽到客戶端試圖建立socket連接時,會為此socket分配一個標識socketDescriptor,該標識在建立服務(wù)器連接時使用,所以應(yīng)提供給每一個線程。接下來派生QRunnable類,并實現(xiàn)純虛函數(shù)run()。

      3.2 程序運行測試

      在Linux環(huán)境下編譯運行服務(wù)器程序結(jié)果如圖2所示。

      圖2 編譯運行

      此時,如圖2所示服務(wù)器已經(jīng)啟動,下面用Linux命令終端的telnet程序模擬一個客戶端,在telnet程序中輸入命令:open 127.0.0.1 1234(此處的127.0.01為程序中的設(shè)置的IP地址,即IPV4的本地主機地址,端口號是1234),請求服務(wù)器進行連接,并對其進行測試,測試結(jié)果如圖3、圖4所示。

      圖3 客戶端

      圖4 服務(wù)器端

      通過以上步驟,利用線程池技術(shù)完成了一個服務(wù)器的創(chuàng)建,即使用 QThreadPool類來運行一個QRunnable對象,它維護了一個線程池。當客戶端請求連接時,服務(wù)器端調(diào)用已經(jīng)創(chuàng)建好的線程池中的一個線程對該客戶端請求進行處理,如圖3所示,服務(wù)器將一個簡單的字符串“Hello world!!”傳遞給客戶端,并在命令客戶端顯示,此時服務(wù)器端打印出為該客戶端服務(wù)的線程ID,如圖4所示。通過以上測試,運用線程池技術(shù)實現(xiàn)了服務(wù)器與客戶端之間的通信。

      4 結(jié)束語

      針對目前多線程服務(wù)器在接受客戶端頻繁連接會增加開銷這一弱點,提出利用Qt線程池技術(shù)減少程序中頻繁創(chuàng)建線程的開銷的優(yōu)勢,在服務(wù)器模型中加入線程池技術(shù)的支持,即利用QThreadPool線程池來管理一組線程,每當有客戶端連接時,就有單個線程對象來處理客戶端請求并交由該線程池管理和回收,從而減少了服務(wù)器頻繁創(chuàng)建線程的開銷,提高服務(wù)器工作效率。但是由于QRunnable并非QObject類,它沒有一個內(nèi)置的與其他組件顯式通訊的方法,必須使用底層的線程原語(比如收集結(jié)構(gòu)的枷鎖保護隊列等)來親自編寫代碼。

      [1] 曾云.基于ARM+QT平臺的嵌入式賓館客服系統(tǒng)軟件設(shè)計[D].上海:東華大學,2011:25-31.

      [2] 劉新強,曾兵義.用線程池解決服務(wù)器并發(fā)請求的方案設(shè)計[J].現(xiàn)代電子技術(shù),2011,34(15):141 -143.

      [3] 黃宇東,胡躍明,陳安.基于Qt的多線程技術(shù)應(yīng)用于研究[J].軟件導刊,2009,8(10):40-42.

      [4] 趙祖龍.基于Qt/Embedded的嵌入式跨平臺聊天系統(tǒng)設(shè)計[J].信息技術(shù),2010,34(12):144 -147.

      [5] 蔡志明,盧傳富,李立夏.精通Qt4編程[M].北京:電子工業(yè)出版社,2008.

      [6] 崔弘珂.一種空間環(huán)境下的TCP傳輸技術(shù)研究[J].無線電通信技術(shù),2011,37(4):21-24.

      [7] 丁林松,黃麗琴.Qt4圖形設(shè)計與嵌入式開發(fā)[M].北京:人民郵電出版社,2009.

      [8] 汪成林.linux環(huán)境下基于SSL的安全文件傳輸系統(tǒng)研究[D].杭州:浙江工業(yè)大學,2012:38-45.

      [9] 馮艷紅,何加銘,楊任爾,等.基于Android藍牙技術(shù)的健康服務(wù)系統(tǒng)設(shè)計[J].無線電通信技術(shù),2014,40(1):61-64.85-88.

      [10]馬睿.基于Qt的TCP網(wǎng)絡(luò)編程研究與應(yīng)用[J].福建電腦,2010,26(11):138 -139.

      猜你喜歡
      監(jiān)聽線程調(diào)用
      千元監(jiān)聽風格Hi-Fi箱新選擇 Summer audio A-401
      核電項目物項調(diào)用管理的應(yīng)用研究
      LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
      網(wǎng)絡(luò)監(jiān)聽的防范措施
      電子制作(2017年20期)2017-04-26 06:58:02
      淺談linux多線程協(xié)作
      基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
      應(yīng)召反潛時無人機監(jiān)聽航路的規(guī)劃
      局域網(wǎng)監(jiān)聽軟件的設(shè)計
      河南科技(2014年5期)2014-02-27 14:08:21
      利用RFC技術(shù)實現(xiàn)SAP系統(tǒng)接口通信
      Linux線程實現(xiàn)技術(shù)研究
      专栏| 罗江县| 赞皇县| 佳木斯市| 涞源县| 闻喜县| 延寿县| 德清县| 奉节县| 左贡县| 大厂| 易门县| 榕江县| 水城县| 新龙县| 屏山县| 南宁市| 蒙山县| 福贡县| 兴仁县| 潼南县| 衡南县| 宜章县| 富顺县| 浠水县| 阳西县| 射洪县| 句容市| 广州市| 黔江区| 军事| 西畴县| 西贡区| 梧州市| 丹凤县| 兖州市| 濮阳县| 西乌珠穆沁旗| 青海省| 潢川县| 铁岭市|