Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt Socket error handling - How to tell the source of error and operation it occurred in



  • I am learning how to use QtWebSocket. I don't see any mention whatsoever of how to handle errors in the documentation beyond:

    QAbstractSocket::SocketError QAbstractSocket::error() const
    Returns the type of error that last occurred.
    
    See also state() and errorString().
    

    and

    void QWebSocket::error(QAbstractSocket::SocketError error)
    This signal is emitted after an error occurred. The error parameter describes the type of 
    error that occurred.
    
    QAbstractSocket::SocketError is not a registered metatype, so for queued connections, you 
    will have to register it with Q_DECLARE_METATYPE() and qRegisterMetaType().
    
    Note: Signal error is overloaded in this class. To connect to this signal by using the 
    function pointer syntax, Qt provides a convenient helper for obtaining the function pointer 
    as shown in this example:
    
    connect(webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
    [=](QAbstractSocket::SocketError error){ /* ... */ });
    See also error() and errorString().
    

    Of course, there is no use of either one in the example code.

    I imagine some errors are going to be common and even expected in a communication layer, such as:

    • list itemTrying to connect to a server that isn't listening
    • Trying to send when the other side hung up
    • Losing network in the middle of a read
    • Losing network in the middle of a send
    • Trying to disconnect a socket that's already disconnected etc

    So, how am I supposed to

    • Know which websocket caused the error?
    • Know what operation it was trying to perform?
    • Control program flow when the error occurs?

  • Qt Champions 2019

    @Fleshbits said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    Know which websocket caused the error?

    Since the signal is coming from the affected socket you know them

    Know what operation it was trying to perform?

    See first

    Control program flow when the error occurs?

    That's up to you



  • @Christian-Ehrlicher said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    @Fleshbits said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    Know which websocket caused the error?

    Since the signal is coming from the affected socket you know them

    Know what operation it was trying to perform?

    See first

    Control program flow when the error occurs?

    That's up to you

    No it really isn't, because what ever operation caused the error to occur has already completed (with failure), so whatever was being sent is lost, whatever was being connected to is gone, I can't throw exceptions at all either way, and I have no idea what operation was occurring. Did the connection drop in the middle of a send? I dunno. In the middle of receive? Who knows. Did the message get through? Part of it? How many bytes? Your guess is as good as mine.

    Hence the question.



  • @Fleshbits
    Well you won't necessarily know half of these answers in any case, e.g. how many bytes did or not get sent/received where. You will have note what the last operation you performed was if you need to know when, say, QWebSocket::error() occurs.



  • @JonB said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    @Fleshbits
    Well you won't necessarily know half of these answers in any case, e.g. how many bytes did or not get sent/received where. You will have note what the last operation you performed was if you need to know when, say, QWebSocket::error() occurs.

    Very confusing.

    With a Berkeley tcp socket I would loop in a send, and it will tell me how many bytes were sent, and I'd keep sending until all my bytes went out. If an error occurred at byte 54, I've literally got a count and it returned an error code, so I know I am sending, I know only 54 bytes made it, and I can reconnect and then send the rest or the whole message again.

    Here, the operations are asynchronous operations that are exited before I am alerted of an error, so I have no information at all. All I know is "NetworkError"

    I dunno how you would keep track of what operation you are performing, because you could be in the middle of sending, when a receive occurred. It's async. You also have no control over when a receive happens and wouldn't be called back until it was complete. So, it's not like I can make some kind of states RECEIVING RECEIVED SENDING SENT CONNECTING CONNECTED DISCONNECTED and have them reflect reality, AFAIK.



  • @Fleshbits said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    With a Berkeley tcp socket I would loop in a send,

    And unless you do your own threading your application would block here, which isn't great in GUI application.

    I know only 54 bytes made it,

    I could easily be wrong here and you may well know more than I, but I thought it only tells you how many bytes made it out of your program and into the OS buffer, not how many were actually sent?

    If you don't like asynchronous operation why don't you make Qt's calls synchronous like you like them to be? Then you will be much closer to the errors occurring while you are performing the operation?



  • @JonB said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    @Fleshbits said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    With a Berkeley tcp socket I would loop in a send,

    And unless you do your own threading your application would block here, which isn't great in GUI application.

    I know only 54 bytes made it,

    I could easily be wrong here and you may well know more than I, but I thought it only tells you how many bytes made it out of your program and into the OS buffer, not how many were actually sent?

    If you don't like asynchronous operation why don't you make Qt's calls synchronous like you like them to be? Then you will be much closer to the errors occurring while you are performing the operation?

    This has nothing to do with blocking vs async, really. Although I follow that you are saying error handling would be simpler. I am not going to implement blocking sockets in a high performance communication layer though.

    Consider boost::asio::tcp

    During an asynchronous send, if an error occured, I would receive a callback with

    • which socket the error occured on
    • how many bytes were sent (to buffers)
    • the error code

    A typical callback setup looks like:

    boost::bind(&Server::handleSend, shared_from_this(),
                                toSend.at(i),
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));
    

    I mean, I am getting that you are telling me that information simply isn't available to me. So OK, let's accept that. What are you guys doing in your application when an error occurs such as network connection lost?

    I imagine I'd have to flag each message "sent" when called back without an error callback occurring and retain it until then? The expected callback won't occur at all if the error callback happens, right?

    For receives, I just won't even know I got anything because I won't be called back until the whole thing arrives, right? I'll just get a network connection lost error and reconnect. The other end will have to handle connection lost.

    For connect, I suppose I just don't allow sends until the connection callback is called back, in effect making my async call sync.

    Does that sound like a solid strategy?


  • Qt Champions 2019

    @Fleshbits If you need to know how many bytes were written you can either use https://doc.qt.io/qt-5/qwebsocket.html#bytesToWrite (you will need to remember how many bytes in total) or use https://doc.qt.io/qt-5/qwebsocket.html#bytesWritten signal.
    I'm not sure what you are after. You send some data, then error occurs - you do know what data you sent, right? So, you can try to send it again.



  • @jsulm said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    @Fleshbits If you need to know how many bytes were written you can either use https://doc.qt.io/qt-5/qwebsocket.html#bytesToWrite (you will need to remember how many bytes in total) or use https://doc.qt.io/qt-5/qwebsocket.html#bytesWritten signal.
    I'm not sure what you are after. You send some data, then error occurs - you do know what data you sent, right? So, you can try to send it again.

    Sounds good.
    Yea, I just want to confirm the nuances. Thanks.



  • @jsulm This doesn't seem to work as expected.
    When I connect it tells me it sent 157 bytes, when I disconnect it tells me I sent 6 bytes, when I actually send something, it tells me it sent bytes, but the bytes don't match the length of the message.

    If I send "Poopy", it tells me 11 bytes were sent.
    Perhaps that is two bytes per character and one terminating null?

    I seem to also get random callbacks that it sent 6 bytes.
    I can't use connected state to disregard all but the actual sends, because these 6 byte callbacks keep occuring randomly while state == connected.

    Maybe those are heartbeat messages? How can I tell the callback that results from a heartbeat, from one that results from a send?


  • Qt Champions 2019

    I don't see how you can ever rely on any counter which tells you that there are n bytes sent and this is the real truth. There are so many buffers involved, including the switches and others in between that a disconnected socket boils down to start over or, when you got an answer from the other side which explicitly told you what bytes were received, start from there. Everything else is useless.



  • @Christian-Ehrlicher said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    I don't see how you can ever rely on any counter which tells you that there are n bytes sent and this is the real truth. There are so many buffers involved, including the switches and others in between that a disconnected socket boils down to start over or, when you got an answer from the other side which explicitly told you what bytes were received, start from there. Everything else is useless.

    If I don't want to have a connected stream of data with acknowledgements built in, why aren't I using UDP?

    My understanding was that websockets are built on top of HTTP, which is on top of TCP, which has "SYN" and "ACK" built in.

    If I have to create my own acknowledgements for every message I send, I might as well drop all the overhead, no?


  • Qt Champions 2019

    @Fleshbits said in Qt Socket error handling - How to tell the source of error and operation it occurred in:

    If I don't want to have a connected stream of data with acknowledgements built in, why aren't I using UDP?

    Because then you also have to check the order and the complete packet.
    With tcp it's guaranteed that the client receives all data, with the correct order. But noone can tell you which bytes the client received when the connection is lost (for whatever reason). Only the client can tell this to you.


Log in to reply