自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解 QT 4中構建多線程服務器

移動開發(fā)
對于服務器來說,多線程的這個特性太有用了,因為多線程使得服務器可能同時響應多個客戶端的請求,所以現在服務器大多采用多線程。

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

而對于服務器來說,多線程的這個特性太有用了,因為多線程使得服務器可能同時響應多個客戶端的請求,所以現在服務器大多采用多線程,所以才會造成我開始的誤解。

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

首先建立一個服務器。新建一個類(Server)繼承QT中的QTcpServer類即可。服務器的職責是監(jiān)聽端口。當監(jiān)聽到有客戶端試圖與服務器建立連接的時候,分配socket與客戶端連接,再進行數據通信。QTcpServer的listen()方法執(zhí)行監(jiān)聽過程,可以指定監(jiān)聽的地址和端口。若給定了QHostAddress類型的監(jiān)聽地址,則監(jiān)聽該地址,否則,監(jiān)聽所有地址;若給定了quint16類型的監(jiān)聽端口,則監(jiān)聽該端口,否則,隨機選定一個監(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有一個虛函數incomingConnection(int socketDescriptor),服務器每當監(jiān)聽到一個客戶端試圖建立連接的時候,會自動調用這個函數,因此,處理這個請求的過程就可以在這個函數中電影,即在子類Server的定義階段,重新定義incomingConnection()這個函數。

對于一個多線程的服務器,每當客戶端試圖連接的時候,服務器應該啟動一個線程,負責對這個客戶端進行服務,所以,incomingConnection()這個函數所要做的就是建立一個線程,而所建立的線程的作用就是對客戶端進行服務,而這其中建立socket連接是基礎。服務器在監(jiān)聽到客戶端試圖建立socket連接時,會為此socket分配一個唯一的標識socketDescriptor,這個標識將在服務器端建立socket連接時使用,所以應提供給每一個線程。

在QT中使用多線程,建立一個類(Thread)繼承QThread類即可。QThread類也有一個虛函數,這個函數是run(),線程建立并啟動(QThread::start())后,就會執(zhí)行這里面的代碼,因此,線程的邏輯過程就應該在run()里面定義。服務器的線程要根據socketDescriptor標識的socket建立連接,然后進行數據通信,所以要將socketDescriptor傳入到Thread中,前面說過,線程是在incomingConnection()里面建立,用構造函數將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.      ...//數據通信      
  11. }     
  12. void run(){    QTcpSocket * socket = new QTcpSocket(socketDescriptor);    ...//數據通信}自此,一個簡單的多線程服務器建立完畢。 

寫的不好,望請指教。

QT4中socket通信

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

我們的系統采用的是C/S結構,所以客戶端與服務器通信是最關鍵,不幸的是,雖然我們沒有用過QT的socket類,我們也沒有估計好通信的難度,等到意識到第一次使用的困難時,已經是第5天了,始終沒有進展,我臨危受命?,F在是第6天,剛剛把通信模塊封裝好,算是對這兩天的突擊的一個回報。

#p#

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

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

  1. view plaincopy to clipboardprint?  
  2. ... // 建立連接,客戶端和服務器端有區(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. ... // 建立連接,客戶端和服務器端有區(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中的數據流<BR>      
  14. ... // 從數據流 in 中讀數據     
  15. ... // 建立連接QDataStream in(&socket);// 接收socket中的數據流... // 從數據流 in 中讀數據 

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

改進后的接收端代碼:

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

但是還是收不到信息,參考了一下別人的程序,再比對一下參考手冊,原來QTcpSocket的爺爺類(其實是父類QAbstractSocket的父類)QIODevice有一個readyRead的信號(signal),當信息準備好并可以讀的時候,這個信號就將發(fā)出,也就是說,只有當這個信號發(fā)出的時候,才可以讀消息。所以要把讀消息的動作read作為一個槽(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ā)一個動作并由這個動作來觸發(fā)socket信號一直也觸發(fā)不了read這個動作。但是我要封裝成一個接口類提供給上層使用,用圖形界面自然是不現實的,于是翻閱了手冊,發(fā)現了一個QAbstractSocket類的一個方法——waitForReadyRead(),這個方法將一直等待到數據可以讀時結束,此時就可以讀數據了。方法也很簡單:

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

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

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

小結:關于詳解 QT 4中構建多線程服務器的內容介紹完了,希望本文對你有所幫助!更多內容請參考編輯推薦。

責任編輯:zhaolei 來源: 互聯網
相關推薦

2011-07-01 10:35:20

QT 多線程 TCP

2009-02-27 11:15:00

多線程服務器MTS專用服務器

2018-01-11 08:24:45

服務器模型詳解

2011-06-13 10:03:19

Qt 多線程 編程

2018-11-28 09:53:50

游戲服務器線程

2011-12-08 13:04:06

JavaNIO

2011-06-30 17:31:32

Qt 多線程 信號

2009-02-18 10:41:16

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

2018-12-20 09:36:24

2010-03-19 14:01:55

Java Socket

2010-03-17 17:54:25

java Socket

2011-06-20 13:43:08

Qt Socket 線程

2010-03-16 10:50:21

Java多線程服務器

2011-06-24 11:12:39

Qt 多線程 線程

2011-06-24 11:03:31

Qt 多線程 線程

2011-03-29 15:30:20

Zabbix服務器

2010-03-16 13:47:48

Java多線程服務器

2015-10-27 09:40:31

TCPIP網絡協議

2011-02-25 16:14:09

proftpdftp

2010-03-31 10:05:40

CentOS Samb
點贊
收藏

51CTO技術棧公眾號