偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

詳解 QT 4中構(gòu)建多線程服務(wù)器

移動開發(fā)
對于服務(wù)器來說,多線程的這個(gè)特性太有用了,因?yàn)槎嗑€程使得服務(wù)器可能同時(shí)響應(yīng)多個(gè)客戶端的請求,所以現(xiàn)在服務(wù)器大多采用多線程。

首先說一下對多線程這個(gè)名詞的理解過程。以前聽說過很多次多線程這個(gè)詞,而且往往與服務(wù)器聯(lián)系起來,因此一直把多線程誤解為服務(wù)器特有的功能;直到這次課程設(shè)計(jì),仔細(xì)學(xué)習(xí)了一下多線程的機(jī)制,才知道真正的意思。簡單的來說,就是同時(shí)有多個(gè)線程一起運(yùn)行,而不同的線程可以執(zhí)行不同的操作。舉個(gè)例子,一個(gè)圖像處理工具,可以用鼠標(biāo)一邊移動圖像,一邊用快捷鍵縮放圖像,此時(shí),移動圖像、縮放圖像就是不同的線程來處理的,如果不支持多線程而是單線程的,那么只能挨個(gè)操作了。

而對于服務(wù)器來說,多線程的這個(gè)特性太有用了,因?yàn)?strong>多線程使得服務(wù)器可能同時(shí)響應(yīng)多個(gè)客戶端的請求,所以現(xiàn)在服務(wù)器大多采用多線程,所以才會造成我開始的誤解。

不管是多線程,還是服務(wù)器QT中已經(jīng)封裝好了特定的類,所以使用起來也很方便。下面建立一個(gè)支持多線程、TCP的服務(wù)器。

首先建立一個(gè)服務(wù)器。新建一個(gè)類(Server)繼承QT中的QTcpServer類即可。服務(wù)器的職責(zé)是監(jiān)聽端口。當(dāng)監(jiān)聽到有客戶端試圖與服務(wù)器建立連接的時(shí)候,分配socket與客戶端連接,再進(jìn)行數(shù)據(jù)通信。QTcpServer的listen()方法執(zhí)行監(jiān)聽過程,可以指定監(jiān)聽的地址和端口。若給定了QHostAddress類型的監(jiān)聽地址,則監(jiān)聽該地址,否則,監(jiān)聽所有地址;若給定了quint16類型的監(jiān)聽端口,則監(jiān)聽該端口,否則,隨機(jī)選定一個(gè)監(jiān)聽端口。

  1. view plaincopy to clipboardprint?  
  2. Server * server = new Server;      
  3. if(!server->listen(host,port)){      
  4. ...//error      
  5. }    

Server * server = new Server;if(!server->listen(host,port)){...//error}QTcpServer有一個(gè)虛函數(shù)incomingConnection(int socketDescriptor),服務(wù)器每當(dāng)監(jiān)聽到一個(gè)客戶端試圖建立連接的時(shí)候,會自動調(diào)用這個(gè)函數(shù),因此,處理這個(gè)請求的過程就可以在這個(gè)函數(shù)中電影,即在子類Server的定義階段,重新定義incomingConnection()這個(gè)函數(shù)。

對于一個(gè)多線程的服務(wù)器,每當(dāng)客戶端試圖連接的時(shí)候,服務(wù)器應(yīng)該啟動一個(gè)線程,負(fù)責(zé)對這個(gè)客戶端進(jìn)行服務(wù),所以,incomingConnection()這個(gè)函數(shù)所要做的就是建立一個(gè)線程,而所建立的線程的作用就是對客戶端進(jìn)行服務(wù),而這其中建立socket連接是基礎(chǔ)。服務(wù)器在監(jiān)聽到客戶端試圖建立socket連接時(shí),會為此socket分配一個(gè)唯一的標(biāo)識socketDescriptor,這個(gè)標(biāo)識將在服務(wù)器端建立socket連接時(shí)使用,所以應(yīng)提供給每一個(gè)線程。

在QT中使用多線程,建立一個(gè)類(Thread)繼承QThread類即可。QThread類也有一個(gè)虛函數(shù),這個(gè)函數(shù)是run(),線程建立并啟動(QThread::start())后,就會執(zhí)行這里面的代碼,因此,線程的邏輯過程就應(yīng)該在run()里面定義。服務(wù)器的線程要根據(jù)socketDescriptor標(biāo)識的socket建立連接,然后進(jìn)行數(shù)據(jù)通信,所以要將socketDescriptor傳入到Thread中,前面說過,線程是在incomingConnection()里面建立,用構(gòu)造函數(shù)將socketDescriptor傳入Thread類,再用socketDescriptor建立socket連接。

定義incomingConnection()

  1. view plaincopy to clipboardprint?  
  2. void incomingConnection(int socketDescriptor){      
  3.      Thread * thread = new Thread(socketDescriptor);      
  4.     thread->start();      
  5. }     
  6. void incomingConnection(int socketDescriptor){    Thread * thread = new Thread(socketDescriptor);    thread->start();}定義run()  
  7. view plaincopy to clipboardprint?  
  8. void run(){      
  9.      QTcpSocket * socket = new QTcpSocket(socketDescriptor);      
  10.      ...//數(shù)據(jù)通信      
  11. }     
  12. void run(){    QTcpSocket * socket = new QTcpSocket(socketDescriptor);    ...//數(shù)據(jù)通信}自此,一個(gè)簡單的多線程服務(wù)器建立完畢。 

寫的不好,望請指教。

QT4中socket通信

最近的軟件工程課程設(shè)計(jì)讓我重新開始使用QT,上次數(shù)據(jù)結(jié)構(gòu)的課程設(shè)計(jì)也是用QT,雖然是做出來了,但是現(xiàn)在想想,那個(gè)時(shí)候?qū)T的理解,或者說得更廣一點(diǎn),對OO的理解,簡直太差勁了,當(dāng)然,人的知識是進(jìn)步的,所以現(xiàn)在有這樣的感受是很正常的。雖然整體的開發(fā)工作還沒有完全結(jié)束,但是已經(jīng)有了很多心得體會,所以特來記錄分享一下。

我們的系統(tǒng)采用的是C/S結(jié)構(gòu),所以客戶端與服務(wù)器通信是最關(guān)鍵,不幸的是,雖然我們沒有用過QT的socket類,我們也沒有估計(jì)好通信的難度,等到意識到第一次使用的困難時(shí),已經(jīng)是第5天了,始終沒有進(jìn)展,我臨危受命?,F(xiàn)在是第6天,剛剛把通信模塊封裝好,算是對這兩天的突擊的一個(gè)回報(bào)。

#p#

我們遇到的問題socket已經(jīng)建立,并且發(fā)送端已經(jīng)將消息發(fā)送,但是接收端始終收不到消息。(我用的socket類型是TCP,也就是QTcpSocket類)

發(fā)送端(發(fā)送端一直不存在問題)代碼如下:

  1. view plaincopy to clipboardprint?  
  2. ... // 建立連接,客戶端和服務(wù)器端有區(qū)別,在此省略<BR>      
  3. QByteArray block;      
  4. QDataStream out(&block,QIODevice::WriteOnly);  // 寫信息至block中,用到QDataStream類<BR>      
  5. socket.write(block);// 信息寫完畢,寫入socket,由socket發(fā)送<BR>      
  6. socket.disconnectFormHost();      
  7. socket.waitForDisconnected();     
  8. ... // 建立連接,客戶端和服務(wù)器端有區(qū)別,在此省略QByteArray block;QDataStream out(&block,QIODevice::WriteOnly);  
  9. // 寫信息至block中,用到QDataStream類socket.write(block);
  10. // 信息寫完畢,寫入socket,由socket發(fā)送socket.disconnectFormHost();socket.waitForDisconnected();有問題的接收端代碼如下:  
  11. view plaincopy to clipboardprint?  
  12. ... // 建立連接<BR>      
  13. QDataStream in(&socket);// 接收socket中的數(shù)據(jù)流<BR>      
  14. ... // 從數(shù)據(jù)流 in 中讀數(shù)據(jù)     
  15. ... // 建立連接QDataStream in(&socket);// 接收socket中的數(shù)據(jù)流... // 從數(shù)據(jù)流 in 中讀數(shù)據(jù) 

以上是最原始的接收和發(fā)送端工作過程,調(diào)試過程中,分別講兩端的socket的狀態(tài)打印出來,結(jié)果是發(fā)送端為A connection is established. 而接收端為The socket has started establishing a connection. 也就是說發(fā)送端正確的建立了連接,并將數(shù)據(jù)寫入,而接收端只是正在建立連接,而并沒有建立好,所以是根本不會受到數(shù)據(jù)的。所以先要確保接收端的連接建立好。waitForConnected()方法就可以解決這個(gè)問題,它將一直等待直到連接已經(jīng)建立。

改進(jìn)后的接收端代碼:

  1. view plaincopy to clipboardprint?  
  2. ... // 建立連接<BR>      
  3. socket.waitForConnected(5000) // 5000表示等待的時(shí)間,默認(rèn)參數(shù)為3000,單位是百萬分之一秒      
  4. QDataStream in(&socket);// 接收socket中的數(shù)據(jù)流<BR>      
  5. ... // 從數(shù)據(jù)流 in 中讀數(shù)據(jù)     
  6. ... // 建立連接socket.waitForConnected(5000)   
  7. // 5000表示等待的時(shí)間,默認(rèn)參數(shù)為3000,單位是百萬分之一秒QDataStream in(&socket);  
  8. // 接收socket中的數(shù)據(jù)流...   
  9. // 從數(shù)據(jù)流 in 中讀數(shù)據(jù)此時(shí),接收端輸出的socket狀態(tài)為A connection is established,連接成功建立。 

但是還是收不到信息,參考了一下別人的程序,再比對一下參考手冊,原來QTcpSocket的爺爺類(其實(shí)是父類QAbstractSocket的父類)QIODevice有一個(gè)readyRead的信號(signal),當(dāng)信息準(zhǔn)備好并可以讀的時(shí)候,這個(gè)信號就將發(fā)出,也就是說,只有當(dāng)這個(gè)信號發(fā)出的時(shí)候,才可以讀消息。所以要把讀消息的動作read作為一個(gè)槽(slot),并將其與readyRead信號連接。

  1. view plaincopy to clipboardprint?  
  2. connect(&socket,SIGNAL(readyRead()),this,SLOT(read()));     
  3. connect(&socket,SIGNAL(readyRead()),this,SLOT(read())); 

但是直接觸發(fā)socket信號,而不用圖形界面的動作來觸發(fā)一個(gè)動作并由這個(gè)動作來觸發(fā)socket信號一直也觸發(fā)不了read這個(gè)動作。但是我要封裝成一個(gè)接口類提供給上層使用,用圖形界面自然是不現(xiàn)實(shí)的,于是翻閱了手冊,發(fā)現(xiàn)了一個(gè)QAbstractSocket類的一個(gè)方法——waitForReadyRead(),這個(gè)方法將一直等待到數(shù)據(jù)可以讀時(shí)結(jié)束,此時(shí)就可以讀數(shù)據(jù)了。方法也很簡單:

  1. view plaincopy to clipboardprint?  
  2. ... // 建立連接<BR>      
  3. socket.waitForConnected(5000) // 5000表示等待的時(shí)間,默認(rèn)參數(shù)為3000,單位是百萬分之一秒<BR>      
  4. if(!socket.waitForReadyRead(3000)){//3000為等待時(shí)間,沒有默認(rèn)的等待時(shí)間,單位是百萬分之一秒      
  5. return ;      
  6. }<BR>      
  7. QDataStream in(&socket);// 接收socket中的數(shù)據(jù)流<BR>      
  8. ... // 從數(shù)據(jù)流 in 中讀數(shù)據(jù)     
  9. ... // 建立連接socket.waitForConnected(5000) // 5000表示等待的時(shí)間,默認(rèn)參數(shù)為3000,單位是百萬分之一秒
  10. if(!socket.waitForReadyRead(3000)){//3000為等待時(shí)間,沒有默認(rèn)的等待時(shí)間,單位是百萬分之一秒return ;  
  11. }  
  12. QDataStream in(&socket);// 接收socket中的數(shù)據(jù)流... // 從數(shù)據(jù)流 in 中讀數(shù)據(jù)這樣,數(shù)據(jù)成功讀取出來,實(shí)現(xiàn)數(shù)據(jù)的通信。 

單向的數(shù)據(jù)傳輸問題解決了,然后再利用單向的數(shù)據(jù)通信組裝成雙向的數(shù)據(jù)通信,這過程中也會遇到不少問題,將在另一篇日志介紹。

原文地址:http://blog.csdn.net/dongfangyu/archive/2010/10/03/5919789.aspx

小結(jié):關(guān)于詳解 QT 4中構(gòu)建多線程服務(wù)器的內(nèi)容介紹完了,希望本文對你有所幫助!更多內(nèi)容請參考編輯推薦。

責(zé)任編輯:zhaolei 來源: 互聯(lián)網(wǎng)
相關(guān)推薦

2011-07-01 10:35:20

QT 多線程 TCP

2009-02-27 11:15:00

多線程服務(wù)器MTS專用服務(wù)器

2018-01-11 08:24:45

服務(wù)器模型詳解

2011-06-13 10:03:19

Qt 多線程 編程

2011-12-08 13:04:06

JavaNIO

2018-11-28 09:53:50

游戲服務(wù)器線程

2011-06-30 17:31:32

Qt 多線程 信號

2010-03-19 14:01:55

Java Socket

2009-02-18 10:41:16

多線程服務(wù)器穩(wěn)定Java

2018-12-20 09:36:24

2010-03-17 17:54:25

java Socket

2011-06-20 13:43:08

Qt Socket 線程

2010-03-16 10:50:21

Java多線程服務(wù)器

2011-03-29 15:30:20

Zabbix服務(wù)器

2011-06-24 11:03:31

Qt 多線程 線程

2011-06-24 11:12:39

Qt 多線程 線程

2010-03-16 13:47:48

Java多線程服務(wù)器

2011-02-25 16:14:09

proftpdftp

2010-03-31 10:05:40

CentOS Samb

2009-09-02 14:23:19

郵件服務(wù)器性
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號