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

2021-10-12 06:53:45 字數 2262 閱讀 9257

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 

2 3 #ifndef tcpmodel_h

4 #define tcpmodel_h

5 #include 6 #include 7 #include 8

9 class tcpmodel:public qobject

10 ;

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

33 class tcpmovetothread: public qobject

34 ;

55 56 #endif // tcpmodel_h

57 58

59 60 #include "tcpmodel.h"

61 #include 62

63 tcpmodel::tcpmodel(qobject* parent)

64 66

67 void tcpmodel::tcpwork()

68 73

74 void tcpmodel::tcpclose()

75 79

80 void tcpmodel::tcpsendmsgslot(qstring msg)

81 85

86 void tcpmodel::tcprecvslot()

87 94 }

95 96

97 98 tcpmovetothread::tcpmovetothread(qobject* parent)

99 111

112 tcpmovetothread::~tcpmovetothread()

113

117

118 void 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...