QLocalSocket multiple messages
-
you should check for
m_socket->bytesAvailable()
before callingQByteArray bytes = m_socket->readAll();
The idea is that the packet has it's size as header (as quint32 for example), so check until bytesAvailable is at least the size of the header, read it and wait until bytesAvailable becomes equal to the size you receive
By wait I mean return
-
@VRonin said:
you should check for
m_socket->bytesAvailable()
before callingQByteArray bytes = m_socket->readAll();
The idea is that the packet has it's size as header (as quint32 for example), so check until bytesAvailable is at least the size of the header, read it and wait until bytesAvailable becomes equal to the size you receive
By wait I mean return
See Client::receivedMessage
void Client::receivedMessage() { // Read all data QByteArray bytes = m_socket->readAll(); QDataStream stream(bytes); stream.setVersion(QDataStream::Qt_5_5); // Read header (quint32) if (m_blockSize == 0) { if (bytes.size() < (int)sizeof(quint32)) { qDebug() << "Client::receivedMessage: Message is small than quint32"; return; } stream >> m_blockSize; } // Read data until m_block.size() == m_blockSize if (m_block.isEmpty()) { m_block = bytes; } else { m_block = m_block.append(bytes); } if (m_block.size() < m_blockSize) { qDebug() << "Client::receivedMessage: Message is smaller than block size"; return; } else { m_blockSize = 0; LocalMessage msg = LocalMessage::fromByteArray(m_block, m_socket->socketDescriptor()); emit message(msg); m_block.clear(); } }
But I dont use bytesAvailable() (because I use header (m_blockSize))
-
@lolopolosko
The point is, that this:if (bytes.size() < (int)sizeof(quint32)) { qDebug() << "Client::receivedMessage: Message is small than quint32"; return; }
will make you skip a message if you don't receive the integer whole (i.e. the 4 bytes at once). It's somewhat unusual to get so little data, but certainly not impossible. Also casting
sizeof
doesn't really make any sense.sizeof
is not a function, but it's a language construct that will be substituted by the compiler with the proper number when generating the binary ... -
@kshegunov
Yes, I know...But wait :-)
I redirect qDebug() to a file, and when I read logs, I dont find message "Client::receivedMessage: Message is small than quint32"; -
@lolopolosko
Well your code looks pretty okay, so if I were you I'd focus my efforts on:LocalMessage::fromByteArray(m_block, m_socket->socketDescriptor());
There's one thing that also caught my eye, you do realize you're including the header size field (the thing you read in
m_blockSize
) in them_block
buffer, right?I still may be missing some subtlety, but currently I don't see anything that's plainly wrong.
Kind regards.
-
@kshegunov
Ok.. Now I changed source code for debuggingI send message directly from my service (without queue)
When client started, service send next messages
TypeMessage::Setting1
TypeMessage::Setting2
TypeMessage::Setting3
TypeMessage::Setting4
TypeMessage::Setting5
TypeMessage::Setting6
TypeMessage::Setting7And client received only next messages:
TypeMessage::Setting1
TypeMessage::Setting2
TypeMessage::Setting4For Client::receivedMessage method I put at the beginning of a method
qDebug() << "Client::receivedMessage: bytesAvailable" << m_socket->bytesAvailable();
Now I see in log file
17:22:14:457 - Client::receivedMessage: bytesAvailable 5243 17:22:14:457 - ClientController::onSocketMessageReceived: TypeMessage::Setting1 17:22:14:495 - Client::receivedMessage: bytesAvailable 187 17:22:14:495 - ClientController::onSocketMessageReceived: TypeMessage:Setting2 17:22:14:496 - Client::receivedMessage: bytesAvailable 572 17:22:14:496 - ClientController::onSocketMessageReceived: TypeMessage:Setting4
But where is another messages I dont know
If I use message queue in Service, I receive all messages (but sometimes some messages lost)
I think problem in Service method
void LocalServer::postData(LocalMessage& message) { QByteArray bytes = message.toByteArray(); if (m_sockets.contains(message.socketDescription)) { if (m_sockets[message.socketDescription]->state() == QLocalSocket::ConnectedState) { m_sockets[message.socketDescription]->write(bytes); m_sockets[message.socketDescription]->flush(); } else { qDebug() << "LocalServer::postData: Socket cannot connected to the server. Current state of socket" << (int)m_sockets[message.socketDescription]->state(); emit error("Socket unconected"); } } else { qDebug() << "LocalServer::postData: Socket with descriptor" << message.socketDescription << "not found"; emit error("Not found socket"); } }
-
@lolopolosko
Could you humor me and output bothm_blockSize
withm_socket->bytesAvailable()
side by side? -
@kshegunov
Hey!! You're right ^_^
But I don't understand.. How it possible??My new log:
I: 22:36:04:211 - Client::receivedMessage: bytesAvailable 6015 I: 22:36:04:213 - Client::receivedMessage: m_blockSize 6011 I: 22:36:04:216 - ClientController::onSocketMessageReceived: TypeMessage::Setting1 I: 22:36:04:255 - Client::receivedMessage: bytesAvailable 337 I: 22:36:04:257 - Client::receivedMessage: m_blockSize 235 I: 22:36:04:259 - ClientController::onSocketMessageReceived: TypeMessage:Setting2 I: 22:36:04:261 - Client::receivedMessage: bytesAvailable 1008 I: 22:36:04:263 - Client::receivedMessage: m_blockSize 334 I: 22:36:04:265 - ClientController::onSocketMessageReceived: TypeMessage:Setting4
QLocalSocket merge data? And how I can unmerge it?
Now I don't understand how it works... :-(P.S.
When readyRead is called, the might be more than one message to be read. -
Ok.. I fix it!
@kshegunov Thank you very much!Now I added \x1C character (INFORMATION SEPARATOR FOUR) at the end message
When client reads data it check if bytesAvailable > m_blockSize and if it true I split data by \x1C character. -
@lolopolosko
Oh, I was just about to suggest you buffer all the received data. But as you've solved your problem then my suggestion is moot. I'm glad it works now.Kind regards.