Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QLocalSocket multiple messages
QtWS: Super Early Bird Tickets Available!

QLocalSocket multiple messages

Scheduled Pinned Locked Moved Solved General and Desktop
qlocalsocketservicewindows
16 Posts 5 Posters 7.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    lolopolosko
    wrote on last edited by
    #1

    Hello everyone

    I've got 2 applications. One client and the other Server (Windows Service)
    Service started and run client automaticly. When client started, it sent message to service that means "I'm running and send me data". Server receive this and send message (about 8-9) to client.
    Some messages has more data (10-20 KB) and some little.
    But when client received data, it lost some messages

    Example:
    From service I send next data
    One
    Two
    Three
    Four
    Five

    And client receive
    One
    Two
    Four
    Five

    I don't know why and how I can fix it...

    And after some time I created MessagesQueue.
    I post data (In service) into queue and timer (100msec) get 3 messages and send to client
    It works now.. But today I reproduce this problem again.. When my local machine freeze (because has a lot of work), I lost some messages.

    Can I fix it and how?

    raven-worxR 1 Reply Last reply
    0
  • raven-worxR Offline
    raven-worxR Offline
    raven-worx Moderators
    replied to lolopolosko on last edited by
    #2

    @lolopolosko
    You can't expect someone to help you find a mistake in your code, without posting the actual code...

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    2
  • L Offline
    L Offline
    lolopolosko
    wrote on last edited by
    #3
    // CLIENT
    void Client::init() {
            m_socket = new QLocalSocket(this);
            m_socket->setReadBufferSize(512000);
            connect(m_socket, SIGNAL(readyRead()), this, SLOT(receivedMessage()));
    }
    
    void Client::receivedMessage() {
        QByteArray bytes = m_socket->readAll();
        QDataStream stream(bytes);
        stream.setVersion(QDataStream::Qt_5_5);
    
        if (m_blockSize == 0) {
            if (bytes.size() < (int)sizeof(quint32)) {
                qDebug() << "Client::receivedMessage: Message is small than quint32";
                return;
            }
    
            stream >> 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();
        }
    }
    
    // SERVICE
    void LocalServer::init() {
        m_server = new QLocalServer(this);
        m_server->setSocketOptions(QLocalServer::OtherAccessOption);
    }
    
    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");
        }
    }
    
    kshegunovK 1 Reply Last reply
    0
  • kshegunovK Offline
    kshegunovK Offline
    kshegunov Moderators
    replied to lolopolosko on last edited by
    #4

    @lolopolosko
    Hello,
    Is it possible you don't receive the whole message and it's somehow discarded?
    By the way, this:

    m_block = m_block.append(bytes);
    

    looks pretty suspicious by itself.

    Read and abide by the Qt Code of Conduct

    L 1 Reply Last reply
    1
  • L Offline
    L Offline
    lolopolosko
    replied to kshegunov on last edited by
    #5

    @kshegunov

    m_block = m_block.append(bytes);
    

    I used it because some messages has bigger than 4096 bytes data
    And QLocalSocket divided this message on small parts

    Is it possible you don't receive the whole message and it's somehow discarded?
    Maybe. But how can I know this?

    How I can debug QLocalSocket between two processes?

    jsulmJ 1 Reply Last reply
    0
  • jsulmJ Offline
    jsulmJ Offline
    jsulm Lifetime Qt Champion
    replied to lolopolosko on last edited by
    #6

    @lolopolosko m_block.append(bytes); is enough no need to assign it to itself

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    2
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #7

    you should check for m_socket->bytesAvailable() before calling QByteArray 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

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    L 1 Reply Last reply
    2
  • L Offline
    L Offline
    lolopolosko
    replied to VRonin on last edited by
    #8

    @VRonin said:

    you should check for m_socket->bytesAvailable() before calling QByteArray 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))

    kshegunovK 1 Reply Last reply
    0
  • kshegunovK Offline
    kshegunovK Offline
    kshegunov Moderators
    replied to lolopolosko on last edited by
    #9

    @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 ...

    Read and abide by the Qt Code of Conduct

    L 1 Reply Last reply
    1
  • L Offline
    L Offline
    lolopolosko
    replied to kshegunov on last edited by
    #10

    @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";

    kshegunovK 1 Reply Last reply
    0
  • kshegunovK Offline
    kshegunovK Offline
    kshegunov Moderators
    replied to lolopolosko on last edited by
    #11

    @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 the m_block buffer, right?

    I still may be missing some subtlety, but currently I don't see anything that's plainly wrong.

    Kind regards.

    Read and abide by the Qt Code of Conduct

    L 1 Reply Last reply
    1
  • L Offline
    L Offline
    lolopolosko
    replied to kshegunov on last edited by lolopolosko
    #12

    @kshegunov
    Ok.. Now I changed source code for debugging

    I 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::Setting7

    And client received only next messages:
    TypeMessage::Setting1
    TypeMessage::Setting2
    TypeMessage::Setting4

    For 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");
        }
    }
    
    kshegunovK 1 Reply Last reply
    0
  • kshegunovK Offline
    kshegunovK Offline
    kshegunov Moderators
    replied to lolopolosko on last edited by kshegunov
    #13

    @lolopolosko
    Could you humor me and output both m_blockSize with m_socket->bytesAvailable() side by side?

    Read and abide by the Qt Code of Conduct

    L 2 Replies Last reply
    1
  • L Offline
    L Offline
    lolopolosko
    replied to kshegunov on last edited by lolopolosko
    #14

    @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.

    1 Reply Last reply
    0
  • L Offline
    L Offline
    lolopolosko
    replied to kshegunov on last edited by
    #15

    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.

    kshegunovK 1 Reply Last reply
    0
  • kshegunovK Offline
    kshegunovK Offline
    kshegunov Moderators
    replied to lolopolosko on last edited by
    #16

    @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.

    Read and abide by the Qt Code of Conduct

    1 Reply Last reply
    0

  • Login

  • Login or register to search.
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved