QT下多執行緒呼叫TCP的問題及可能的解決方案

2022-08-26 23:06:16 字數 2293 閱讀 4813

1. 能否跨執行緒呼叫tcp套接字?

對於tcp通訊,乙個常見的操作就是讀寫分開,即讀寫分別在不同執行緒中執行,這樣實現實時全雙工通訊,那麼在qt中能否實現讀寫執行緒分開呢?理論上將是不可以的,但是實際操作發現能實現(會有錯誤警告)。

這涉及到訊號和槽的連線方式。通常qt的訊號和槽有三種常用的連線方式:

(1) qt::autoconnection:qt預設連線方式。當訊號接收方與訊號傳送方在同一執行緒時,等價於qt::directconnection;否則等價於qt::queuedconnection。

(2) qt::directconnection: 當訊號被傳送後,槽函式立即執行。這對於實時通訊意義重大,如ui介面傳送tcp訊息之後,需要實時等待tcp響應以進行不同的操作,這種連線方式就能保證tcp能立即傳送訊息。

2紅色部分是修改部分,即採用了qt::directconnection。由於訊號傳送方在ui執行緒,接收方在tcp子執行緒,所以此時呼叫的槽函式不會在子執行緒中執行,而是直接在ui執行緒執行,這樣收發在不同執行緒,都能實時響應。這種做法雖然沒有影響收發效果,但是每次會提示socket notifiers cannot be enabled or disabled from another thread,從提示結果就能看出這是跨執行緒呼叫tcp造成的。這種提示的後果未知(因為程式仍能正常執行)。

2. 如何優化設計

雖然1所介紹的方案能實現功能,但是畢竟出現錯誤提示,不知道會造成何種後果。所以最好還是不採用以上方式。那麼對於tcp的收發,如何做到實時響應呢?

造成1中的程式原因是在tcp子執行緒一直迴圈接收tcp資料,這種操作是非常不明智的。為了讓tcp子執行緒空閒,只在收發資料時執行,可以將tcp接收也改為訊號和槽的形式。tcp收到訊息時,會傳送訊號qtcpsocket::readyread,通過該訊號與tcp接收繫結,就不用在子執行緒中迴圈呼叫tcp接收函式了。改造後的tcpmodel如下:

1

#ifndef tcpmodel_h

4#define tcpmodel_h

5 #include 6 #include 7 #include 8

9class tcpmodel:public

qobject10;

3132

//將tcpmodel在qml初始化時移入到子執行緒

33class tcpmovetothread: public

qobject34;

5556

#endif

//tcpmodel_h

5758

59//

tcpmodel.cpp

60 #include "

tcpmodel.h

"61 #include 62

63 tcpmodel::tcpmodel(qobject*parent)

6466

67void

tcpmodel::tcpwork()

6873

74void

tcpmodel::tcpclose()

7579

80void

tcpmodel::tcpsendmsgslot(qstring msg)

8185

86void

tcpmodel::tcprecvslot()

8794}95

9697

98 tcpmovetothread::tcpmovetothread(qobject*parent)

99111

112 tcpmovetothread::~tcpmovetothread()

113117

118void

tcpmovetothread::datachangedslot(qstring msg)

119

主要改動都用紅色標出了,特別注意:

第83行:qt的tcp通訊預設都是非同步的,所以即時呼叫了write和read函式,也可能不會立即進行讀寫,表現在程式中就是能立即執行槽函式,但tcp收發有明顯延遲(可以將83注釋掉,再看現象)。所以為了將非同步改為同步,qt的tcp規定了以下函式:

waitforconnected() 等待鏈結的建立

waitforreadyread() 等待新資料的到來

waitforbyteswritten() 等待資料寫入socket

waitfordisconnected() 等待鏈結斷開

QT下多執行緒呼叫TCP的問題及可能的解決方案

1.能否跨執行緒呼叫tcp套接字?對於tcp通訊,乙個常見的操作就是讀寫分開,即讀寫分別在不同執行緒中執行,這樣實現實時全雙工通訊,那麼在qt中能否實現讀寫執行緒分開呢?理論上將是不可以的,但是實際操作發現能實現 會有錯誤警告 這涉及到訊號和槽的連線方式。通常qt的訊號和槽有三種常用的連線方式 1 ...

QT下的多執行緒

一.多執行緒的使用 繼承qthread類,重寫protected void run 函式,則此run函式即為多執行緒將執行的函式,ui類組合此類,呼叫start 函式即開啟此執行緒,並執行run函式 h class test1 public qthread cpp void test1 run vo...

Qt多執行緒中呼叫QTimer

ifndef mythread h define mythread h include class qtimer class mythread public qthread endif mythread h 原始檔如下 include mythread.h include include mythr...