2015-09-16 44 views
1

我嘗試使用QTcpSserver,這將與保持連接,並且一次只有一個客戶端,直到客戶端斷開連接。所以,我在客戶端留下了一個成員指針。我可以在deleteLater之後再次使用QTcpSocket進行另一個連接嗎?

問題出現在這裏:在我看到的互聯網上的例子中,在disconnected()之後,它被稱爲deleteLater()。很好,但我會再次使用這個類成員指針來進行另一個連接。請記住,服務器一次只保留一個客戶端。那麼,如果在分配了另一個連接之後套接字對象被刪除呢?

我的意思是:

class TcpServer(QObject* o) : public QTcpServer { 
... 
private: 
    QTcpSocket* client; 
} 

void TcpServer::connected() { 
    client = this->nextPendingConnection(); 
    this->pauseAccepting(); 
    connect(client, SIGNAL(disconnected()), client, SLOT(clientDisconnected())); 
} 

void TcpServer::clientDisconnected() { 
    client->deleteLater(); 
    this->resumeAccepting(); 
} 

的情況是這樣的:

  1. 客戶端連接。因此,client = nextPendingConnection();

  2. 服務器已暫停收聽。不接受新的連接。

  3. 客戶端斷開連接。需要發佈client。因此,client->deleteLater()被調用。

  4. 服務器繼續收聽。

  5. 新的連接來。所以,我需要client = nextPendingConnection();

,以前client對象被刪除了?也許?也許不會?如果事件循環嘗試刪除client,在步驟5中將新連接分配給它之後該怎麼辦?

那麼,我將如何保持一個且只有一個客戶端,同時刪除以前斷開連接的客戶端?

如果我這樣做會安全嗎?

void TcpServer::clientDisconnected() 
{ 
    QSocket* ptr = client; 
    ptr->deleteLater(); 
    ... 
} 
+0

根據您的場景,我認爲您應該有一個tcp套接字池,您可以創建和刪除,而不必擔心前一個套接字是否已成功刪除。如果你真的只想使用一個套接字,你應該聽「destroy()」信號,然後調用resumeAccepting() –

+0

「銷燬:這個信號在對象obj被銷燬之前立即發出,並且不能被阻塞。 「這意味着任何我會在這個信號槽內寫入的東西,都會在對象被銷燬後被調用,對吧?所以,這似乎是問題的答案。如果你寫了,我會接受。 –

回答

2

我舉Qt文檔看:

對象將被刪除時,控制返回到事件循環。

所以deleteLater()是延遲delete。只要撥打電話deleteLater(),該物品即被視爲已刪除。

您的nextPendingConnection()調用將創建另一個對象,需要稍後再刪除。

然而,在你的情況下,你只允許一個掛起的連接,如你所說,並禁止接受,直到客戶端斷開連接。我這種情況下它應該是安全的,在其他情況下,你可以覆蓋你的客戶端指針,並將失去對它的控制(內存泄漏)。

即使你的情況,我寧願這樣的解決方案:

void TcpServer::clientDisconnected() 
{ 
    if (qobject_cast<QAbstractSocket*>(sender())) { 
     sender()->deleteLater(); 
    } 
    ... 
} 

如果超過允許一個連接在你的應用程序的未來變化這也將是安全的。

+0

不是我的「如果我這樣做會安全嗎?」部分與'sender()'解決方案几乎相同? –

+0

但是我在分配客戶端時停止接受新的連接,所以連接()在clientDisconnected()運行之前永遠不會被觸發。 –

+0

不一定,因爲建立一個新的連接並不意味着以前的連接斷開,即'clientDisconnected()'從來沒有爲此調用過。但我監督你的'pauseAccepting()'調用。在這種情況下,我不確定首先調用哪個插槽,或者如果確保在連接之前調用斷開連接。我建議不要使用一個客戶端指針,或使用sender()對象來引用正確的對象。我也不確定如果在調用pauseAccepting()之前還有一些掛起的連接符號在隊列中會發生什麼。 – bkausbk

0

據我瞭解nextPendingConnection();將返回指向新QTcpSocket類對象,所以你沒有什麼可擔心的。

deleteLater()將只安排刪除您的舊對象。 QTcpSocket* client只包含指向QTcpSocket類對象的指針。當你打電話給deleteLater()時Qt只會刪除在調用這個函數時指向的對象client

+0

我擔心的是,如果deleteLater()在deleteLater()真正運行時指向客戶端指向的內存,現在又調用它了,那該怎麼辦呢? –

+0

別擔心。它不會查找當前的「客戶端」。在執行時沒有「客戶端」和其他名稱,只是指針。當你給'client'賦值時,它將失去與舊對象的所有連接,deleteLater()將在稍後刪除這個舊對象。如果你忘記調用deleteLater(),那麼所有的舊對象都將作爲垃圾保存在內存中。 –

+0

是的,我也認爲這一定是真的。 –

相關問題