2017-08-10 96 views
0

考慮通過tcp套接字將200個檢測器連接到程序的情況。他們非常頻繁地發送他們的數據,並且我想盡可能有效地處理它。從多個tcp連接讀取數據

我可以考慮2種方法來解決這個問題,但我在QT方面很新,所以我不知道哪一個更好。

  1. 創建將運行從QRunnable()衍生的200個對象線程池,每個對象將包括一個插座和槽將被連接到該插座的信號,使關於一個檢測器的所有數據將被處理在那一個對象中。 (在run()方法中會有QEventLoop)

  2. 創建200個對象,每個對象將由套接字組成,並將這200個套接字信號連接到主線程中的一個插槽。所以它將在一個插槽中處理來自200個檢測器的數據。

哪種方法會更好consdering,在第一種方法會出現創建200個QEventLoops(每個對象)的事實呢?

+0

好的舊'poll()'/'epoll()'有什麼問題?你不需要一堆線程來處理類似的事情。 –

+0

Research'select()'函數。它旨在使單線程可以監視多個輸入通道。還有一些東西需要研究:函數調用比線程上下文切換快大約1000倍。 –

+0

據我所知,Qt在QEventLoop的後臺使用select()(事件循環處於休眠狀態,直到內核事件發送給應用程序),那麼我的第二種方法有什麼問題?如果我錯了,請糾正我。 – notfound404

回答

0

有沒有必要直接到epoll。例如,你可以使用像uvw這樣專用的東西。

+0

在我看來,如果他打算使用第三方網絡API,那麼顯而易見的將是Qt API的網絡組件,他已經在使用其他的東西。否則,他增加了一個額外的依賴項,沒有明顯的補償收益。 –

+0

如果建議直接使用epoll(),那麼第三方網絡庫的優勢顯而易見:便攜性和易用性。但是,如果Qt性能可以接受,那麼他們是明顯的選擇。不過,他必須避免200個線程。 – Praise

0

我認爲任何解決方案都可以工作,但我絕對推薦避免每個連接線程的解決方案,因爲200個線程大約198個線程太多,並且效率不高。

我會這樣做的方式是創建一個線程並在該線程內運行select()(或poll()或epoll()或其他)事件循環來處理那裏的200個TCP連接,使用非阻塞I/O。當數據到達該線程時,該線程可以將數據解析爲合適的數據塊,然後通過Queued信號/槽連接(或qApp-> postEvent()if)將解析/組合數據發送到主線程(如果需要)你更喜歡這樣做)。 (在單獨的線程中進行聯網有助於防止GUI操作干擾網絡性能,反之亦然)反之亦然

在網絡線程中創建〜200個QTCPSocket對象(並使網絡線程運行Qt標準QEventLoop處理它們)也可能工作得很好;上一次我試圖說我遇到了Qt在某些平臺上實現網絡的一些性能問題,但這又回到了Qt4的時代,所以我對Qt從那時起提高了它的實現效率感到樂觀。

+0

謝謝你的回答,但是我從來沒有建議使用~200線程,而是使用QThreadPool和默認的maxThreadCount()設置爲QThread :: idealThreadCount(),但我現在看到了這個解決方案的弱點。 我想我會在一個線程中創建所有套接字並將它們的信號連接到一個插槽,之後我將利用QThread中QEventLoop的優勢來處理套接字事件。我希望它會有效率。 – notfound404

0

在所有情況下,您不需要比邏輯處理器內核更多的線程。在線程中分配對象。使用旋轉事件回調的QRunnable是毫無意義的,即使我承認在某人的請求中以回答的方式展示它。 Eventloops也不便宜 - 每個都需要幾千字節的堆棧,至少在我的平臺上。因此,最好使用QThread,每個線程有一個單一的eventloop,然後以循環方式在線程之間分配網絡對象。