[英]Wait for response from server on client
I'm trying to validate a user's login, so I send a username and password to the server, the server checks that data against the database, and will send a yes/no if the validation was a success or failure. 我正在尝试验证用户的登录名,因此我向服务器发送了用户名和密码,服务器根据数据库检查了该数据,如果验证成功或失败,则会发送是/否。 The client receives this and the readyRead() signal is emitted, and I handle that with a slot. 客户端收到此消息,并发出readyRead()信号,我使用一个插槽来处理它。
I have this login function: 我有这个登录功能:
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
}
I want to wait for a response from the server before I return a true or false with login
. 我想等待服务器的响应,然后用login
返回true或false。 I know how to accept a response from the server just fine, but I basically want the data to be sent, and the client program to stop until either we get a response or some time has passed and we get a time out. 我知道如何很好地接受来自服务器的响应,但是我基本上希望发送数据,并且客户端程序将停止,直到我们获得响应或一段时间后才超时。
How do I do this in Qt? 如何在Qt中做到这一点?
http://qt-project.org/doc/qt-4.8/qiodevice.html#waitForReadyRead 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
}
I didn't look through the docs properly. 我没有正确查看文档。 I found my answer. 我找到了答案。
You really do not want to write code like that. 你真的不想写这样的代码。 Remember that all waitFor...
and exec
methods can reenter your code and thus are a source of hard to find bugs. 请记住,所有的waitFor...
和exec
方法都可以重新输入您的代码,因此是难以发现错误的来源。 No, they will reenter at the most inopportune moment. 不,他们将在最不适当的时刻重新进入。 Perhaps when you're demoing to a client, or perhaps when you've shipped your first system to Elbonia :) 也许当您向客户进行演示时,或者当您将第一个系统交付给Elbonia时:)
The client should emit a signal when the login
succeeds. login
成功后,客户端应发出信号。 There's a request to login, and a response to such a request. 有一个登录请求,以及对此请求的响应。 You can use the QStateMachine
to direct the overall application's logic through such responses. 您可以使用QStateMachine
通过此类响应来指导整个应用程序的逻辑。
The example below presumes that the network protocol supports more than one request "on the wire" at any time. 下面的示例假定网络协议随时都支持一个以上的请求。 It'd be simple to get rid of the handler queue and allow just one handler. 摆脱处理程序队列并只允许一个处理程序很简单。
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);
};
You could use a circular queue for the buffer to speed things up if you're transmitting lots of data. 如果要传输大量数据,则可以对缓冲区使用循环队列以加快处理速度。 As-is, the remaining data is shoved to the front of the buffer after each response is processed. 照原样,在处理完每个响应之后,会将剩余数据推到缓冲区的前面。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.