出錯和經驗
2009-04-28 15:43:48
閱讀12
字型大小:大
中小
訂閱qt4中構建多執行緒的伺服器
首先說一下對多執行緒
這個名詞的理解過程。以前聽說過很多次多執行緒這個詞,而且往往與
伺服器聯絡起來,因此一直把多執行緒誤解為伺服器特有的功能;直到這次
課程設計
,仔細 學習
了一下多執行緒的機制,才知道真正的意思。簡單的來說,就是同時有多個執行緒一起執行,而不同的執行緒可以執行不同的操作。舉個例子,乙個影象處理工具,可以用滑鼠一邊移**像,一邊用快捷鍵縮放影象,此時,移**像、縮放影象就是不同的執行緒來處理的,如果不支援多執行緒而是單執行緒的,那麼只能挨個操作了。
而對於伺服器來說,多執行緒的這個特性太有用了,因為多執行緒使得伺服器可能同時響應多個客戶端的請求,所以現在伺服器大多採用多執行緒,所以才會造成我開始的誤解。
不管是多執行緒,還是伺服器,qt中已經封裝好了特定的類,所以使用起來也很方便。
下面建立
乙個支援多執行緒、tcp的伺服器。
首先建立乙個伺服器。新建乙個類(server)繼承qt中的qtcpserver類即可。伺服器的職責是監聽埠。當監聽到有客戶端試圖與伺服器建立連線的時候,分配socket
與客戶端連線,再進行資料通訊
。qtcpserver的listen()方法執行監聽過程,可以指定監聽的位址和埠。若給定了qhostaddress型別的監聽位址,則監聽該位址,否則,監聽所有位址;若給定了quint16型別的監聽埠,則監聽該埠,否則,隨機選定乙個監聽埠。
view plain
copy to clipboard
?server * server =newserver;
if(!server->listen(host,port))
qtcpserver有乙個虛函式incomingconnection(int socketdescriptor),伺服器每當監聽到乙個客戶端試圖建立連線的時候,會自動呼叫這個函式,因此,處理這個請求的過程就可以在這個函式中電影,即在子類server的定義階段,重新定義incomingconnection()這個函式。對於乙個多執行緒的伺服器,每當客戶端試圖連線的時候,伺服器應該啟動乙個執行緒,負責對這個客戶端進行服務,所以,incomingconnection()這個函式所要做的就是建立乙個執行緒,而所建立的執行緒的作用就是對客戶端進行服務,而這其中建立socket連線是基礎。伺服器在監聽到客戶端試圖建立socket連線時,會為此socket分配乙個唯一的標識socketdescriptor,這個標識將在伺服器端建立socket連線時使用,所以應提供給每乙個執行緒。
在qt中使用多執行緒,建立乙個類(thread)繼承qthread類即可。qthread類也有乙個虛函式,這個函式是run(),執行緒建立並啟動(qthread::start())後,就會執行這裡面的**,因此,執行緒的邏輯過程就應該在run()裡面定義。伺服器的執行緒要根據socketdescriptor標識的socket建立連線,然後進行資料通訊,所以要將socketdescriptor傳入到thread中,前面說過,執行緒是在incomingconnection()裡面建立,用建構函式將socketdescriptor傳入thread類,再用socketdescriptor建立socket連線。
定義incomingconnection()
view plain
copy to clipboard
?voidincomingconnection(intsocketdescriptor)
定義run()
view plain
copy to clipboard
?voidrun()
自此,乙個簡單的多執行緒伺服器建立完畢。
寫的不好,望請指教。
*************************===
qt4中socket通訊最
近的軟體工程
課程設計讓我重新開始使用qt,上次資料結構的課程設計
也是用qt,雖然是做出來了,但是現在想想,那個時候對qt的理解,或者說得更廣一點,對oo的理解,簡直太差勁了,當然,人的知識是進步的,所以現在有這樣的感受是很正常的。雖然整體的開發工作還沒有完全結束,但是已經有了很多心得體會,所以特來記錄分享一下。
我們的系統採用的是c/s結構,所以客戶端與伺服器
通訊是最關鍵,不幸的是,雖然我們沒有用過qt的socket
類,我們也沒有估計好通訊
的難度,等到意識到第一次使用的困難時,已經是第5天了,始終沒有進展,我臨危受命。現在是第6天,剛剛把通訊模組封裝好,算是對這兩天的突擊
的乙個回報。
我們遇到的問題socket已經建立
,並且傳送端已經將訊息傳送,但是接收端始終收不到訊息。(我用的socket型別是tcp,也就是qtcpsocket類)
傳送端(傳送端一直不存在問題)**如下:
view plain
copy to clipboard
?... // 建立連線,客戶端和伺服器端有區別,在此省略
qbytearray block;
qdatastream out(&block,qiodevice::writeonly); // 寫資訊至block中,用到qdatastream類
socket.write(block);// 資訊寫完畢,寫入socket,由socket傳送
socket.disconnectformhost();
socket.waitfordisconnected();
有問題的接收端**如下:
view plain
copy to clipboard
?... // 建立連線
qdatastream in(&socket);// 接收socket中的資料流
... // 從資料流 in 中讀資料
以上是最原始的接收和傳送端工作過程,除錯過程中,分別講兩端的socket的狀態列印出來,結果是傳送端為a connection is established. 而接收端為the socket has started establishing a connection. 也就是說傳送端正確的建立了連線,並將資料寫入,而接收端只是正在建立連線,而並沒有建立好,所以是根本不會受到資料的。所以先要確保接收端的連線建立好。waitforconnected()方法就可以解決這個問題,它將一直等待直到連線已經建立。
改進後的接收端**:
view plain
copy to clipboard
?... // 建立連線
socket.waitforconnected(5000) // 5000表示等待的時間,預設引數為3000,單位是百萬分之一秒
qdatastream in(&socket);// 接收socket中的資料流
... // 從資料流 in 中讀資料
此時,接收端輸出的socket狀態為a connection is established,連線成功建立。
但是還是收不到資訊,參考了一下別人的程式,再比對一下參考手冊,原來qtcpsocket的爺爺類(其實是父類qabstractsocket的父類)qiodevice有乙個readyread的訊號(signal),當資訊準備好並可以讀的時候,這個訊號就將發出,也就是說,只有當這個訊號發出的時候,才可以讀訊息。所以要把讀訊息的動作read作為乙個槽(slot),並將其與readyread訊號連線。
view plain
copy to clipboard
?connect(&socket,signal(readyread()),this,slot(read()));
但是直接觸發socket訊號,而不用圖形介面的動作來觸發乙個動作並由這個動作來觸發socket訊號一直也觸發不了read這個動作。但是我要封裝成乙個介面類提供給上層使用,用圖形介面自然是不現實的,於是翻閱了手冊,發現了乙個qabstractsocket類的乙個方法——waitforreadyread(),這個方法將一直等待到資料可以讀時結束,此時就可以讀資料了。方法也很簡單:
view plain
copy to clipboard
?... // 建立連線
socket.waitforconnected(5000) // 5000表示等待的時間,預設引數為3000,單位是百萬分之一秒
if(!socket.waitforreadyread(3000))
qdatastream in(&socket);// 接收socket中的資料流
... // 從資料流 in 中讀資料
這樣,資料成功讀取出來,實現資料的通訊。
單向的資料傳輸問題解決了,然後再利用單向的資料通訊組裝成雙向的資料通訊,這過程中也會遇到不少問題,將在另一篇日誌介紹。
QT4中構建多執行緒的伺服器
而對於伺服器來說,多執行緒的這個特性太有用了,因為多執行緒使得伺服器可能同時響應多個客戶端的請求,所以現在伺服器大多採用多執行緒,所以才會造成我開始的誤解。不管是多執行緒,還是伺服器,qt中已經封裝好了特定的類,所以使用起來也很方便。下面建立乙個支援多執行緒 tcp的伺服器。首先建立乙個伺服器。新建...
詳解 QT 4中構建多執行緒伺服器
首先說一下對多執行緒這個名詞的理解過程。以前聽說過很多次多執行緒這個詞,而且往往與伺服器聯絡起來,因此一直把多執行緒誤解為伺服器特有的功能 直到這次課程設計,仔細學習了一下多執行緒的機制,才知道真正的意思。簡單的來說,就是同時有多個執行緒一起執行,而不同的執行緒可以執行不同的操作。舉個例子,乙個影象...
構建多執行緒的伺服器
簡單的來說,就是同時有多個執行緒一起執行,而不同的執行緒可以執行不同的操作。舉個例子,乙個影象處理工具,可以用滑鼠一邊移 像,一邊用快捷鍵縮放影象,此時,移 像 縮放影象就是不同的執行緒來處理的,如果不支援多執行緒而是單執行緒的,那麼只能挨個操作了。而對於伺服器來說,多執行緒的這個特性太有用了,因為...