2017-08-25 82 views
0

我寫QT5一個簡單的TCP服務器,其任務可以簡化爲:的Qt的TCPSocket :: readyRead不triggerd在特定情況下

  • 監聽連接端口

  • 人後連接到它,從中讀取一個字符串,然後打印字符串

  • 關閉套接字,並監聽下一個連接

服務器的代碼是這樣的:

class Server:public QObject 
{ 
    Q_OBJECT 
public: 
    QTcpServer* TcpServer; 
    QTcpSocket* TcpSocket; 
    void Start(); 
public slots: 
    void OnConnection(); 
}; 


void Server::Start() 
{ 
    TcpServer = new QTcpServer(); 
    TcpServer->listen(QHostAddress::Any, 9999); 
    connect(TcpServer, &QTcpServer::newConnection, this, &Server::OnConnection); 
} 


void Server::OnConnection() 
{ 
    qDebug() << "connected"; 
    TcpSocket = TcpServer->nextPendingConnection(); 
    connect(TcpSocket, &QTcpSocket::readyRead, this, [=]() 
    { 
     qDebug() << "received:" << TcpSocket->readAll(); 
     TcpSocket->close(); 
    }); 
} 

然後,我有這樣的代碼片段客戶:

QTcpSocket socket; 
socket.connectToHost(QHostAddress::LocalHost, 9999); 
auto x = QString("Some information").toUtf8(); 
socket.write(x); 
socket.close(); 

這段代碼工作正常,如果我只在一個控制檯應用程序運行,或在我的項目在這裏運行:

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; // main window of my application 
    w.show(); 

    QTcpSocket socket; 
    socket.connectToHost(QHostAddress::LocalHost, 9999); 
    auto x = QString("Some information").toUtf8(); 
    socket.write(x); 
    socket.close(); 

    return a.exec(); 
} 

這裏是一個讓我困惑的部分:

在主窗口中有一個QPushButton,它的clicked信號連接到一個插槽,在這個插槽中我將調用一個包含代碼片段的函數。該函數主要處理設置主窗口的佈局(我使用QStackedWidget),並且在執行代碼片段時,它的工作方式不同。

從服務器的日誌中我認爲套接字可以連接到服務器,但不能觸發QTcpSocket::readyRead,所以即使代碼段中的所有五行都已被執行,服務器總是等待數據(在我提供的代碼中,服務器的日誌只會在沒有以下數據的情況下「連接」)。

我不知道爲什麼服務器的QTcpSocket::readyRead不能觸發,如果我把它放在這個函數中。有人可以解釋嗎?

感謝您閱讀我的問題:-)

+0

我想你應該在關閉客戶端套接字之前添加http://doc.qt.io/qt-5/qiodevice.html#waitForBytesWritten方法調用。 – Macias

回答

0

當你寫的控制檯應用程序,這是確定使用你的代碼片段,其中一些修改,因爲你沒有對付阻塞GUI。只需使用以下方法:
waitForConnected
waitForByttesWritten

但是,如果你寫一個GUI您shold使用的信號。
首先呼叫connectToHost後,等待connected 信號。然後你可以寫你的數據。

之後,等待bytesWritten信號並確保bytes參數等於由write方法返回的值。當一切正常時,您可以關閉插座。