Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Staring Qt network programming
QtWS25 Last Chance

Staring Qt network programming

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
19 Posts 3 Posters 599 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.
  • Q qcoderpro

    @J-Hilk

    It's used here:
    connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Server::displayError); for displaying the errors. I don't think it'd be possible by using the tcpServer only. Disagree?

    J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by
    #8

    @qcoderpro said in Staring Qt network programming:

    Disagree

    in principle, no I do not disagree. Listing to the error Signal of your socket is a good thing :D

    but, you're neither sending nor receiving data with that socket. That is all done, like @jsulm said,
    here:

    void Server::onNewConnection()
    {
        QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
        connect(clientConnection, &QAbstractSocket::disconnected,
                clientConnection, &QObject::deleteLater);
        in.setDevice(clientConnection);
        in.setVersion(QDataStream::Qt_4_0);
        connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
    }
    

    That socket is correctly cleaned up thumbs up but you're not listening to the error signal :D


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

    1 Reply Last reply
    1
    • jsulmJ jsulm

      @qcoderpro But where are you doing anything with this socket?!
      The fact that you connect one signal from that socket to a slot does not mean that this socket is doing manythig useful...
      You get the socket from tcpServer->nextPendingConnection(), so why do you need tcpSocket?

      Q Offline
      Q Offline
      qcoderpro
      wrote on last edited by qcoderpro
      #9

      @jsulm @J-Hilk
      I didn't know that since I'm very new to network programming. So you mean to remove the tcpSocket and that connect() from the server app and call the displayError slot this way?

      void Server::onNewConnection()
      {
          QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
         connect(clientConnection , &QAbstractSocket::errorOccurred, this, &Server::displayError);
          connect(clientConnection, &QAbstractSocket::disconnected,
                  clientConnection, &QObject::deleteLater);
          in.setDevice(clientConnection);
          in.setVersion(QDataStream::Qt_4_0);
          connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
      }
      
      J.HilkJ 1 Reply Last reply
      0
      • Q qcoderpro

        @jsulm @J-Hilk
        I didn't know that since I'm very new to network programming. So you mean to remove the tcpSocket and that connect() from the server app and call the displayError slot this way?

        void Server::onNewConnection()
        {
            QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
           connect(clientConnection , &QAbstractSocket::errorOccurred, this, &Server::displayError);
            connect(clientConnection, &QAbstractSocket::disconnected,
                    clientConnection, &QObject::deleteLater);
            in.setDevice(clientConnection);
            in.setVersion(QDataStream::Qt_4_0);
            connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
        }
        
        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #10

        @qcoderpro said in Staring Qt network programming:

        I didn't know that since I'm very new to network programming. So you mean to remove the tcpSocket and that connect() from the server app and call the displayError slot this way?

        yes, or, if you want to keep a pointer to the socket as a class member variable, you could do:

        void Server::onNewConnection()
        {
           if(tcpSocket)
             //Some warning or other error handling, because old connection is still in use!
            return;
        
            tcpSocket = tcpServer->nextPendingConnection();
           connect(tcpSocket , &QAbstractSocket::errorOccurred, this, &Server::displayError);
            connect(tcpSocket, &QAbstractSocket::disconnected,
                    tcpSocket, [=] () ->void{
            //A Lambda, so we can also reset the pointer to nullptr
            tcpSocket->deleteLater();
            tcpSocket = nullptr;
        });
            in.setDevice(tcpSocket);
            in.setVersion(QDataStream::Qt_4_0);
            connect(tcpSocket, &QAbstractSocket::readyRead, this, &Server::writeMessage);
        }
        

        you would still have to remove the new QTcpSocket from your constructor and initialise tcpSocket as nullptr for this to work.


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        Q 1 Reply Last reply
        1
        • J.HilkJ J.Hilk

          @qcoderpro said in Staring Qt network programming:

          I didn't know that since I'm very new to network programming. So you mean to remove the tcpSocket and that connect() from the server app and call the displayError slot this way?

          yes, or, if you want to keep a pointer to the socket as a class member variable, you could do:

          void Server::onNewConnection()
          {
             if(tcpSocket)
               //Some warning or other error handling, because old connection is still in use!
              return;
          
              tcpSocket = tcpServer->nextPendingConnection();
             connect(tcpSocket , &QAbstractSocket::errorOccurred, this, &Server::displayError);
              connect(tcpSocket, &QAbstractSocket::disconnected,
                      tcpSocket, [=] () ->void{
              //A Lambda, so we can also reset the pointer to nullptr
              tcpSocket->deleteLater();
              tcpSocket = nullptr;
          });
              in.setDevice(tcpSocket);
              in.setVersion(QDataStream::Qt_4_0);
              connect(tcpSocket, &QAbstractSocket::readyRead, this, &Server::writeMessage);
          }
          

          you would still have to remove the new QTcpSocket from your constructor and initialise tcpSocket as nullptr for this to work.

          Q Offline
          Q Offline
          qcoderpro
          wrote on last edited by
          #11

          @J-Hilk

          Since, as stated earlier, I'm very new to network programming, let me please start from beginning to figure out the things properly and be sure about that.
          Let's start from the server app. In server.cpp starting from top, we have tcpServer(new QTcpServer(this)) { }.
          Here tcpSever is an object whose job is to listen to incoming connections (tcpSockets) and accept one or a number of them. We initialize it and pass the program/project's pointer (this) to it as the parent.
          Next in:

           //   tcpServer = new QTcpServer(this);
              if(!tcpServer->listen())
                  return "Server Unable to start the server: " +
                          tcpServer->errorString();
          
              connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection);
          

          we probably can remove the first line which is repetitive! Then the tcpServer will listen on all network interfaces for incoming connections/tcpSockets (IP + port number) and returns an error if it fails listening.
          If a connection arrives, connect() invokes the onNewConnection slot.
          Completely right up to this point, please?

          J.HilkJ 1 Reply Last reply
          0
          • Q qcoderpro

            @J-Hilk

            Since, as stated earlier, I'm very new to network programming, let me please start from beginning to figure out the things properly and be sure about that.
            Let's start from the server app. In server.cpp starting from top, we have tcpServer(new QTcpServer(this)) { }.
            Here tcpSever is an object whose job is to listen to incoming connections (tcpSockets) and accept one or a number of them. We initialize it and pass the program/project's pointer (this) to it as the parent.
            Next in:

             //   tcpServer = new QTcpServer(this);
                if(!tcpServer->listen())
                    return "Server Unable to start the server: " +
                            tcpServer->errorString();
            
                connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection);
            

            we probably can remove the first line which is repetitive! Then the tcpServer will listen on all network interfaces for incoming connections/tcpSockets (IP + port number) and returns an error if it fails listening.
            If a connection arrives, connect() invokes the onNewConnection slot.
            Completely right up to this point, please?

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #12

            @qcoderpro said in Staring Qt network programming:

            Completely right up to this point, please?

            yes,

            see I didn't even notice the 2nd QTcpServer instance, the problem if you just "scroll" through it :D


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            Q 1 Reply Last reply
            2
            • J.HilkJ J.Hilk

              @qcoderpro said in Staring Qt network programming:

              Completely right up to this point, please?

              yes,

              see I didn't even notice the 2nd QTcpServer instance, the problem if you just "scroll" through it :D

              Q Offline
              Q Offline
              qcoderpro
              wrote on last edited by
              #13

              @J-Hilk

              see I didn't even notice the 2nd QTcpServer instance, the problem if you just "scroll" through it :D

              Yeah, no problem, thanks for your kindness. :)
              Moving on, we reach this slot:

              void Server::onNewConnection()
              {
                  QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
                  connect(clientConnection, &QAbstractSocket::errorOccurred, this, &Server::displayError);
                  connect(clientConnection, &QAbstractSocket::disconnected,
                          clientConnection, &QObject::deleteLater);
                  in.setDevice(clientConnection);
                  in.setVersion(QDataStream::Qt_4_0);
                  connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
              }
              

              in which we have clientConnection that is a QTcpSocket representing the server side of the connection!

              1. But I assume that clientConnection is the one we have already sent from the client app to this server's connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and caused the above slot to be invoked! I believe we don't need two tcpSockets, one already sent to the server and another created inside the server the way above! Agree?
              2. In the next connect(), we call the displayError in case of any connection error. Connection errors may happen due to the Internet, operating system or the hardware failures. Using QAbstractSocket::errorOccurred we try to catch and then show them to the user. Right?
              3. Using the second connect() in the slot above, we aim to delete the clientConnection when we later on exit the slot! But this is ambiguous! If the clientConnection was the one we already sent from the client app, why should we delete it when we exit the slot (onNewConnection)? So something in my assumptions should not be correct!
              jsulmJ J.HilkJ 2 Replies Last reply
              0
              • Q qcoderpro

                @J-Hilk

                see I didn't even notice the 2nd QTcpServer instance, the problem if you just "scroll" through it :D

                Yeah, no problem, thanks for your kindness. :)
                Moving on, we reach this slot:

                void Server::onNewConnection()
                {
                    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
                    connect(clientConnection, &QAbstractSocket::errorOccurred, this, &Server::displayError);
                    connect(clientConnection, &QAbstractSocket::disconnected,
                            clientConnection, &QObject::deleteLater);
                    in.setDevice(clientConnection);
                    in.setVersion(QDataStream::Qt_4_0);
                    connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
                }
                

                in which we have clientConnection that is a QTcpSocket representing the server side of the connection!

                1. But I assume that clientConnection is the one we have already sent from the client app to this server's connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and caused the above slot to be invoked! I believe we don't need two tcpSockets, one already sent to the server and another created inside the server the way above! Agree?
                2. In the next connect(), we call the displayError in case of any connection error. Connection errors may happen due to the Internet, operating system or the hardware failures. Using QAbstractSocket::errorOccurred we try to catch and then show them to the user. Right?
                3. Using the second connect() in the slot above, we aim to delete the clientConnection when we later on exit the slot! But this is ambiguous! If the clientConnection was the one we already sent from the client app, why should we delete it when we exit the slot (onNewConnection)? So something in my assumptions should not be correct!
                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by jsulm
                #14

                @qcoderpro said in Staring Qt network programming:

                one already sent to the server and another created inside the server

                1. Sockets are not send to anywhere. You have one socket on the client side and one on the server side and both communicate with each other. The socket on the server side is the one you get using tcpServer->nextPendingConnection(). These two sockets are two different objects living in two different processes (and usually on different machines)!
                2. Yes
                3. As said in 1.: sockets are not send to anywhere!

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

                1 Reply Last reply
                2
                • Q qcoderpro

                  @J-Hilk

                  see I didn't even notice the 2nd QTcpServer instance, the problem if you just "scroll" through it :D

                  Yeah, no problem, thanks for your kindness. :)
                  Moving on, we reach this slot:

                  void Server::onNewConnection()
                  {
                      QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
                      connect(clientConnection, &QAbstractSocket::errorOccurred, this, &Server::displayError);
                      connect(clientConnection, &QAbstractSocket::disconnected,
                              clientConnection, &QObject::deleteLater);
                      in.setDevice(clientConnection);
                      in.setVersion(QDataStream::Qt_4_0);
                      connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage);
                  }
                  

                  in which we have clientConnection that is a QTcpSocket representing the server side of the connection!

                  1. But I assume that clientConnection is the one we have already sent from the client app to this server's connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and caused the above slot to be invoked! I believe we don't need two tcpSockets, one already sent to the server and another created inside the server the way above! Agree?
                  2. In the next connect(), we call the displayError in case of any connection error. Connection errors may happen due to the Internet, operating system or the hardware failures. Using QAbstractSocket::errorOccurred we try to catch and then show them to the user. Right?
                  3. Using the second connect() in the slot above, we aim to delete the clientConnection when we later on exit the slot! But this is ambiguous! If the clientConnection was the one we already sent from the client app, why should we delete it when we exit the slot (onNewConnection)? So something in my assumptions should not be correct!
                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #15

                  @qcoderpro

                  Yeah, no problem, thanks for your kindness. :)

                  no problem I think we have a very pleasant conversation/exchange, I like it :D

                  1But I assume that clientConnection is the one we have already sent from the client app to this server's connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and caused the above slot to be invoked! I believe we don't need two tcpSockets, one already sent to the server and another created inside the server the way above! Agree?

                  I'm not sure what you mean, you're not literally sending a socket via the network ? You're creating one on the server side and one on the client side and those communicate with each other.
                  The QTCPServer is creating the socket and you get pointer to it via the nextPendingConnection call, so you're actually not (explicitly) creating a QTcpSocket instance on your own.

                  In the next connect(), we call the displayError in case of any connection error. Connection errors may happen due to the Internet, operating system or the hardware failures. Using QAbstractSocket::errorOccurred we try to catch and then show them to the user. Right?

                  well, off all those
                  https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum
                  and yes unplugging the hardware cable etc should generate an error you can catch here
                  8926b6e4-ef56-480a-a2b3-be48ab7a4bec-image.png

                  Using the second connect() in the slot above, we aim to delete the clientConnection when we later on exit the slot! But this is ambiguous! If the clientConnection was the one we already sent from the client app, why should we delete it when we exit the slot (onNewConnection)? So something in my assumptions should not be correct!

                  sockets aren't sent anywhere, they are parented to the QTcpServer instance, but when you don't need them anymore, you should delete them to free memory, thats what the delete later is for.
                  https://doc.qt.io/qt-5/qtcpserver.html#nextPendingConnection

                  The socket is created as a child of the server, which means that it is automatically deleted when the QTcpServer object is destroyed. It is still a good idea to delete the object explicitly when you are done with it, to avoid wasting memory.


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  1 Reply Last reply
                  2
                  • Q Offline
                    Q Offline
                    qcoderpro
                    wrote on last edited by
                    #16

                    @J-Hilk @jsulm
                    OK, thank you both. To clarify the dark things more, I run both projects and type the IP address, port number (provided by the server) and a "Hi" message on the client app and click on the Send button on it. The message will be printed on the server's UI.

                    tretet.PNG

                    Let's explore what happens one by one.

                    1. A socket is an endpoint instance in a communication through a computer network and is defined by an IP address and a port number. So the first socket is (192.168.56.1 and 53386) and either of the apps is an endpoint. We send that socket (I mean that IP and port) to the server app which will be caught by the connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and this, in turn, invokes the onNewConnection slot. There, a new socket (the server's side one) will be created to form the connection with the first socket from the client, completely. Therefore, communications through networks are made via sockets and through them data will be exchanged too. Agree with these all, please?

                    2. For the clientConnection socket, the displayError will aim at catching errors (if any) and that socket is then set for deletion when we exit the onNewConnection slot.

                    3. Then we assign clientConnection to be the device the DataStream in will use for data exchange as the output and the first socket will act like input for that data.

                    Agree with 2 & 3 too?

                    J.HilkJ 1 Reply Last reply
                    0
                    • Q qcoderpro

                      @J-Hilk @jsulm
                      OK, thank you both. To clarify the dark things more, I run both projects and type the IP address, port number (provided by the server) and a "Hi" message on the client app and click on the Send button on it. The message will be printed on the server's UI.

                      tretet.PNG

                      Let's explore what happens one by one.

                      1. A socket is an endpoint instance in a communication through a computer network and is defined by an IP address and a port number. So the first socket is (192.168.56.1 and 53386) and either of the apps is an endpoint. We send that socket (I mean that IP and port) to the server app which will be caught by the connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); and this, in turn, invokes the onNewConnection slot. There, a new socket (the server's side one) will be created to form the connection with the first socket from the client, completely. Therefore, communications through networks are made via sockets and through them data will be exchanged too. Agree with these all, please?

                      2. For the clientConnection socket, the displayError will aim at catching errors (if any) and that socket is then set for deletion when we exit the onNewConnection slot.

                      3. Then we assign clientConnection to be the device the DataStream in will use for data exchange as the output and the first socket will act like input for that data.

                      Agree with 2 & 3 too?

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #17

                      @qcoderpro said in Staring Qt network programming:

                      Agree with these all, please

                      no, but close enough

                      For the clientConnection socket, the displayError will aim at catching errors (if any)

                      yes

                      and that socket is then set for deletion when we exit the onNewConnection slot.

                      no, its set for deletion when the socket connection is lost, not for the scope end of onNewConnection, as the QTcpSocket is heap allocated.

                      Then we assign clientConnection to be the device the DataStream in will use for data exchange as the output and the first socket will act like input for that data.

                      yes


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      Q 1 Reply Last reply
                      1
                      • J.HilkJ J.Hilk

                        @qcoderpro said in Staring Qt network programming:

                        Agree with these all, please

                        no, but close enough

                        For the clientConnection socket, the displayError will aim at catching errors (if any)

                        yes

                        and that socket is then set for deletion when we exit the onNewConnection slot.

                        no, its set for deletion when the socket connection is lost, not for the scope end of onNewConnection, as the QTcpSocket is heap allocated.

                        Then we assign clientConnection to be the device the DataStream in will use for data exchange as the output and the first socket will act like input for that data.

                        yes

                        Q Offline
                        Q Offline
                        qcoderpro
                        wrote on last edited by
                        #18

                        @J-Hilk

                        no, but close enough

                        1. Is the statement "We send that socket (I mean ..." what you disagree with, please, or other things in 1) too?

                        its set for deletion when the socket connection is lost

                        1. When is that connection lost, please? Is it when we close both projects (or one of them)? I say that because when we once send the IP and port number to the server and the connection is that way established, we can send as many messages as we wish to, without sending the IP and port number another time.

                        2. For the line in.setVersion(QDataStream::Qt_4_0); we can use QDataStream::Qt_6_3 rather than that version 4 but the important matter is that the other app ought to use the same version too. Right?

                        3. And the connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage); will invoke the the slot writeMessage when the QDataStream in notifies its device's socket (clientConnection) that a message has completely arrived from the sender and is now ready to read. Right?

                        Q 1 Reply Last reply
                        0
                        • Q qcoderpro

                          @J-Hilk

                          no, but close enough

                          1. Is the statement "We send that socket (I mean ..." what you disagree with, please, or other things in 1) too?

                          its set for deletion when the socket connection is lost

                          1. When is that connection lost, please? Is it when we close both projects (or one of them)? I say that because when we once send the IP and port number to the server and the connection is that way established, we can send as many messages as we wish to, without sending the IP and port number another time.

                          2. For the line in.setVersion(QDataStream::Qt_4_0); we can use QDataStream::Qt_6_3 rather than that version 4 but the important matter is that the other app ought to use the same version too. Right?

                          3. And the connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::writeMessage); will invoke the the slot writeMessage when the QDataStream in notifies its device's socket (clientConnection) that a message has completely arrived from the sender and is now ready to read. Right?

                          Q Offline
                          Q Offline
                          qcoderpro
                          wrote on last edited by
                          #19

                          No more help!? :(

                          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