簡體   English   中英

等待客戶端上服務器的響應

[英]Wait for response from server on client

我正在嘗試驗證用戶的登錄名,因此我向服務器發送了用戶名和密碼,服務器根據數據庫檢查了該數據,如果驗證成功或失敗,則會發送是/否。 客戶端收到此消息,並發出readyRead()信號,我使用一個插槽來處理它。

我有這個登錄功能:

bool Client::login(QString username, QString password){

    //some code

    client.write(clientSendBuf); //send the data to the server
    //wait for response
    //if response is good, return true
    //else return false
}

我想等待服務器的響應,然后用login返回true或false。 我知道如何很好地接受來自服務器的響應,但是我基本上希望發送數據,並且客戶端程序將停止,直到我們獲得響應或一段時間后才超時。

如何在Qt中做到這一點?

http://qt-project.org/doc/qt-4.8/qiodevice.html#waitForReadyRead

QTcpSocket client;

if(client.waitForReadyRead(15000)){
    //do something if signal is emitted
}
else{
    //timeout
}

我沒有正確查看文檔。 我找到了答案。

你真的不想寫這樣的代碼。 請記住,所有的waitFor...exec方法都可以重新輸入您的代碼,因此是難以發現錯誤的來源。 不,他們在最不適當的時刻重新進入。 也許當您向客戶進行演示時,或者當您將第一個系統交付給Elbonia時:)

login成功后,客戶端應發出信號。 有一個登錄請求,以及對此請求的響應。 您可以使用QStateMachine通過此類響應來指導整個應用程序的邏輯。

下面的示例假定網絡協議隨時都支持一個以上的請求。 擺脫處理程序隊列並只允許一個處理程序很簡單。

class Client : public QObject {
  Q_OBJECT
  typedef bool (Client::*Handler)(); // returns true when the request is finished
  QTcpSocket m_client;
  QByteArray m_buffer;
  QQueue<Handler> m_responses; // always has the idle response on the bottom
  ...
  Q_SLOT void hasData() {
    Q_ASSERT(! m_responses.isEmpty());
    m_buffer += m_client.readAll();
    while (! m_buffer.isEmpty()) {
      if (m_reponses.head()()) m_responses.dequeue();
    }
  }
  bool processIdleRsp() {
    // Signal an error condition, we got data but expect none!
    return false; // Must never return true, since this response mustn't be dequeued.
  }
  bool processLoginRsp() {
    const int loginRspSize = ...;
    if (m_buffer.size() < loginRspSize) return false;
    bool success = false;
    ... // process the response
    emit loginRsp(success);
    m_buffer = m_buffer.mid(loginRspSize); // remove our response from the buffer
    return true;
  }
public:
  Client(QObject * parent = 0) : QObject(parent), m_state(Idle) {
    connect(&m_client, SIGNAL(readyRead()), SLOT(hasData());
    m_responses.enqueue(&Client::processIdleRsp);
  }
  Q_SLOT void loginReq(const QString & username, const QString & password) {
    QByteArray request;
    QDataStream req(&request, QIODevice::WriteOnly);
    ...
    m_client.write(request);
    m_responses.enqueue(&Client::processLoginRsp);
  }
  Q_SIGNAL void loginRsp(bool success);
};

如果要傳輸大量數據,則可以對緩沖區使用循環隊列以加快處理速度。 照原樣,在處理完每個響應之后,會將剩余數據推到緩沖區的前面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM