我正在尝试验证用户的登录信息,因此我向服务器发送用户名和密码,服务器会根据数据库检查数据,如果验证成功或失败,则会发送“是/否”。客户端收到此信息并发出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中执行此操作?
答案 0 :(得分:1)
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
}
我没有正确查看文档。我找到了答案。
答案 1 :(得分:0)
你真的不想要编写这样的代码。请注意,所有waitFor...
和exec
方法都可以重新输入您的代码,因此是很难找到错误的来源。不,他们将重新进入最不合时宜的时刻。也许当您向客户演示时,或者当您将第一个系统发送到Elbonia时:)
当login
成功时,客户端应发出信号。有登录请求和对此类请求的响应。您可以使用QStateMachine
通过此类响应来指导整个应用程序的逻辑。
以下示例假设网络协议支持多个请求"在线路上#34;随时。它很容易摆脱处理程序队列并只允许一个处理程序。
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);
};
如果你传输大量数据,你可以使用循环队列来缓冲缓冲区。按原样,在处理完每个响应后,其余数据将被推送到缓冲区的前面。