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. QTcpServer and listening on multiple ports
Forum Updated to NodeBB v4.3 + New Features

QTcpServer and listening on multiple ports

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 4 Posters 3.8k Views 1 Watching
  • 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.
  • Kent-DorfmanK Offline
    Kent-DorfmanK Offline
    Kent-Dorfman
    wrote on last edited by
    #2

    @steveq said in QTcpServer and listening on multiple ports:

    QTcpServer::listen only allows you to listen to the one port. Is there a way to listen on a port range (ie: 7770:7800)?

    No. TCP is session oriented, so it is essentially point-to-point. You can connect multiple clients to a single TCP port, and the server must differentiate between the individual sessions. In the POSIX world this was historically done by forking the server process so that each session had its own server process running. Aggregating multiple sessions under a single server process is more complicated.

    Am I approaching this the wrong way perhaps?

    I doubt your clients are all under the same WAN address. More likely your server is sitting behind NAT so it has a single hidden address but presents a single public IP to the WAN. For the clients to get thru to the NATTed server your router must do port forwarding when an external client wishes to make a connection.

    Even if your clients themselves are NATTed on the other end, the routers should handle remapping to the correct IP if you are using TCP.

    1 Reply Last reply
    4
    • S steveq

      Hey All,

      I suspect I haven't quite grasped how QTcpServer works.

      I'm writing a (not so) simple network chat program. I've realised that to chat to more than one client on the same WAN address, I need to use multiple ports (with NAT rules on the router).

      QTcpServer::listen only allows you to listen to the one port. Is there a way to listen on a port range (ie: 7770:7800)?

      Am I approaching this the wrong way perhaps?

      It seems like a simple enough solution, but it currently eludes me.

      Thanks in advance for your help.

      Steve Q. :-)

      aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by aha_1980
      #3

      @steveq

      just to add to @Kent-Dorfman, you are looking for https://doc.qt.io/qt-5/qtcpserver.html#newConnection and https://doc.qt.io/qt-5/qtcpserver.html#nextPendingConnection

      No need for multiple ports, threads or forking.

      Regards

      Edit: https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application might be interesting for you, too.

      Qt has to stay free or it will die.

      1 Reply Last reply
      2
      • S Offline
        S Offline
        steveq
        wrote on last edited by
        #4

        Hey @Kent-Dorfman and @aha_1980,
        Thanks so much for your prompt replies!

        So I still think I'm not getting this.

        The scenario I was talking about is this:
        Let's say I have a static IP address of 1.2.3.4 and I am using port 7770 to chat on. The router connected to that IP address has a NAT rule in it port forwarding 1.2.3.4:7770 to 192.168.1.2:7770. Now lets say I have a second machine on the same IP 1.2.3.4 and it has a LAN IP address of 192.168.1.3. We also want to chat to this machine. I can''t see how to do it unless I use another port so the router would have a rule 1.2.3.4:7771 to 192.168.1.3:7771.

        Does this make sense? My TCP listener would have to monitor both ports (although obviously not as I am not getting it!!).

        @aha_1980 I use newConnection and nextPendingConnection already. In fact my software is running really well when talking to machine, I just can't get my head around how to connect to to different machines behind the same static IP.

        Here is where I set up my server:

        	// Listen for any chat requests
        	m_pChatTcpServer = new QTcpServer(this);
        
        	connect(m_pChatTcpServer, SIGNAL(newConnection()), this, SLOT(chatNewConnection()));
        	connect(m_pChatTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(chatServerError(QAbstractSocket::SocketError)));
        
        	m_pChatTcpServer->listen(QHostAddress::Any, static_cast<quint16>(m_settings.chatPort));
        

        And where I get a newConnection:

        // Called when a new chat connection comes in without us asking for it (m_pChatTcpServer)
        void MainWindow::chatNewConnection()
        {
        	 SQTcpSocket *socket = static_cast<SQTcpSocket *>(m_pChatTcpServer->nextPendingConnection());
        
        	 // Temporarily connect these signals until I am ready to hand this socket off to my ClientServer object
        	 connect(socket, SIGNAL(readyRead()), this, SLOT(chatReadyRead()),Qt::UniqueConnection);
        	 connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(chatConnectionError(QAbstractSocket::SocketError)),Qt::UniqueConnection);
        	 connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(chatTcpSocketState(QAbstractSocket::SocketState)),Qt::UniqueConnection);
        	 connect(socket, SIGNAL(disconnected()), this, SLOT(chatOnConnectionTerminated()),Qt::ConnectionType(Qt::UniqueConnection));
        	 connect(socket, SIGNAL(connected()), this, SLOT(chatOnConnectionEstablished()),Qt::UniqueConnection);
        }
        

        And then receiving the message form the server

        // Here for convenience in case I ever need it. Does nothing because any ready will be done once the socket is handed off to my ClientServer class
        void MainWindow::chatReadyRead()
        {
        	SQTcpSocket *socket = static_cast<SQTcpSocket *>(sender());
        
        	while(socket->bytesAvailable())
        	{
        		QByteArray receivedData = socket->readAll();
        
        		QDataStream ds1(receivedData.mid(0, 4));
        
        		ds1.setByteOrder(QDataStream::LittleEndian);
        
        		int messageSize;
        		ds1 >> messageSize;
        
        		QDataStream ds2(receivedData.mid(4, 4));
        
        		ds2.setByteOrder(QDataStream::LittleEndian);
        
        		int messageType;
        		ds2 >> messageType;
        
        		switch( messageType)
        		{
        			// Initial hand shaking message
        			case CHATMESSAGE_HELLO:
        			{
        				QString uuid, nameColour, nickName;
        
        				uuid = receivedData.mid(8, 32);
        
        				nameColour = receivedData.mid(40, 7);
        				nickName = receivedData.mid(47, -1);
        
        				// Reply back with my initial HELLO (using the same uuid so we both appear in the correct chat tab) message with the nick name colour and nick name
        				unsigned int messageType = CHATMESSAGE_HELLO;
        
        				QByteArray l_vDataToBeSent;
        
        				QDataStream l_vStream(&l_vDataToBeSent, QIODevice::WriteOnly);
        
        				l_vStream.setByteOrder(QDataStream::LittleEndian);
        
        				unsigned int size = sizeof(messageType) + static_cast<unsigned int>(m_settings.nickNameColour.length()) + static_cast<unsigned int>(m_settings.nickName.length()) + static_cast<unsigned int>(uuid.length());
        
        				l_vStream << size;
        
        				l_vStream << messageType;
        
        				l_vDataToBeSent.append(uuid);
        				l_vDataToBeSent.append(m_settings.nickNameColour);
        				l_vDataToBeSent.append(m_settings.nickName);
        
        				if ( socket ) socket->write(l_vDataToBeSent, l_vDataToBeSent.length());
        
        				// Now start the new chat
        				startNewChat( socket, uuid, nameColour, nickName );
        
        				break;
        			}
        		}
        	}
        }
        

        Thanks in advance guys, I think I am totally missing how this works here.

        Regards,

        Steve Q.

        aha_1980A 1 Reply Last reply
        0
        • S steveq

          Hey @Kent-Dorfman and @aha_1980,
          Thanks so much for your prompt replies!

          So I still think I'm not getting this.

          The scenario I was talking about is this:
          Let's say I have a static IP address of 1.2.3.4 and I am using port 7770 to chat on. The router connected to that IP address has a NAT rule in it port forwarding 1.2.3.4:7770 to 192.168.1.2:7770. Now lets say I have a second machine on the same IP 1.2.3.4 and it has a LAN IP address of 192.168.1.3. We also want to chat to this machine. I can''t see how to do it unless I use another port so the router would have a rule 1.2.3.4:7771 to 192.168.1.3:7771.

          Does this make sense? My TCP listener would have to monitor both ports (although obviously not as I am not getting it!!).

          @aha_1980 I use newConnection and nextPendingConnection already. In fact my software is running really well when talking to machine, I just can't get my head around how to connect to to different machines behind the same static IP.

          Here is where I set up my server:

          	// Listen for any chat requests
          	m_pChatTcpServer = new QTcpServer(this);
          
          	connect(m_pChatTcpServer, SIGNAL(newConnection()), this, SLOT(chatNewConnection()));
          	connect(m_pChatTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(chatServerError(QAbstractSocket::SocketError)));
          
          	m_pChatTcpServer->listen(QHostAddress::Any, static_cast<quint16>(m_settings.chatPort));
          

          And where I get a newConnection:

          // Called when a new chat connection comes in without us asking for it (m_pChatTcpServer)
          void MainWindow::chatNewConnection()
          {
          	 SQTcpSocket *socket = static_cast<SQTcpSocket *>(m_pChatTcpServer->nextPendingConnection());
          
          	 // Temporarily connect these signals until I am ready to hand this socket off to my ClientServer object
          	 connect(socket, SIGNAL(readyRead()), this, SLOT(chatReadyRead()),Qt::UniqueConnection);
          	 connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(chatConnectionError(QAbstractSocket::SocketError)),Qt::UniqueConnection);
          	 connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(chatTcpSocketState(QAbstractSocket::SocketState)),Qt::UniqueConnection);
          	 connect(socket, SIGNAL(disconnected()), this, SLOT(chatOnConnectionTerminated()),Qt::ConnectionType(Qt::UniqueConnection));
          	 connect(socket, SIGNAL(connected()), this, SLOT(chatOnConnectionEstablished()),Qt::UniqueConnection);
          }
          

          And then receiving the message form the server

          // Here for convenience in case I ever need it. Does nothing because any ready will be done once the socket is handed off to my ClientServer class
          void MainWindow::chatReadyRead()
          {
          	SQTcpSocket *socket = static_cast<SQTcpSocket *>(sender());
          
          	while(socket->bytesAvailable())
          	{
          		QByteArray receivedData = socket->readAll();
          
          		QDataStream ds1(receivedData.mid(0, 4));
          
          		ds1.setByteOrder(QDataStream::LittleEndian);
          
          		int messageSize;
          		ds1 >> messageSize;
          
          		QDataStream ds2(receivedData.mid(4, 4));
          
          		ds2.setByteOrder(QDataStream::LittleEndian);
          
          		int messageType;
          		ds2 >> messageType;
          
          		switch( messageType)
          		{
          			// Initial hand shaking message
          			case CHATMESSAGE_HELLO:
          			{
          				QString uuid, nameColour, nickName;
          
          				uuid = receivedData.mid(8, 32);
          
          				nameColour = receivedData.mid(40, 7);
          				nickName = receivedData.mid(47, -1);
          
          				// Reply back with my initial HELLO (using the same uuid so we both appear in the correct chat tab) message with the nick name colour and nick name
          				unsigned int messageType = CHATMESSAGE_HELLO;
          
          				QByteArray l_vDataToBeSent;
          
          				QDataStream l_vStream(&l_vDataToBeSent, QIODevice::WriteOnly);
          
          				l_vStream.setByteOrder(QDataStream::LittleEndian);
          
          				unsigned int size = sizeof(messageType) + static_cast<unsigned int>(m_settings.nickNameColour.length()) + static_cast<unsigned int>(m_settings.nickName.length()) + static_cast<unsigned int>(uuid.length());
          
          				l_vStream << size;
          
          				l_vStream << messageType;
          
          				l_vDataToBeSent.append(uuid);
          				l_vDataToBeSent.append(m_settings.nickNameColour);
          				l_vDataToBeSent.append(m_settings.nickName);
          
          				if ( socket ) socket->write(l_vDataToBeSent, l_vDataToBeSent.length());
          
          				// Now start the new chat
          				startNewChat( socket, uuid, nameColour, nickName );
          
          				break;
          			}
          		}
          	}
          }
          

          Thanks in advance guys, I think I am totally missing how this works here.

          Regards,

          Steve Q.

          aha_1980A Offline
          aha_1980A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on last edited by aha_1980
          #5

          @steveq You cannot have multiple maschines with the same IP in one network.

          NAT port forwarding still works with one server port only. The trick with port forwarding is, that different client IP addresses are mapped to one address (the NAT routers address), but different client ports.

          For your server, thats transparent.

          Edit: clarified port forwarding more

          Qt has to stay free or it will die.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            steveq
            wrote on last edited by
            #6

            @aha_1980 okay, so I have two versions of my software running on two different machines both with unique LAN IP addresses (192.168.1.2 and 192.168.1.3), but the static IP address for my premises on the internet is provided by my ISP (1.2.3.4) and is the same for both machines, that is if you Google whatismyipaddress, they both have the same "internet" address, but unique LAN addresses. The NAT in the router won't let me forward my chat port (7770) to them both, and even if it did, both machines would get the one message.

            This is doing my head in!! Lol

            Sorry again in advance, I seem to be making this harder than it need to be.

            Steve Q.

            aha_1980A 1 Reply Last reply
            0
            • Kent-DorfmanK Offline
              Kent-DorfmanK Offline
              Kent-Dorfman
              wrote on last edited by Kent-Dorfman
              #7

              I think the thing you don't make clear is your chat architecture. Is it a chat mesh network, or a single master server and multiple clients that all go thru that server? That is the configuration you need to implement. Having multiple chat servers is going to gum up things. You need one master/server that manages and rebroadcasts to relevant clients.

              Rather than worrying about implementation details you need to formalize your system architecture first.

              1 Reply Last reply
              3
              • S steveq

                @aha_1980 okay, so I have two versions of my software running on two different machines both with unique LAN IP addresses (192.168.1.2 and 192.168.1.3), but the static IP address for my premises on the internet is provided by my ISP (1.2.3.4) and is the same for both machines, that is if you Google whatismyipaddress, they both have the same "internet" address, but unique LAN addresses. The NAT in the router won't let me forward my chat port (7770) to them both, and even if it did, both machines would get the one message.

                This is doing my head in!! Lol

                Sorry again in advance, I seem to be making this harder than it need to be.

                Steve Q.

                aha_1980A Offline
                aha_1980A Offline
                aha_1980
                Lifetime Qt Champion
                wrote on last edited by
                #8

                @steveq you should draw yourself a topology picture and understand how the data flow is.

                Remember that port forwarding is only for the server.

                The client establishes a connection to 1.2.3.4, which is an internet address so the packet leaves your local net. then your router sends the packet back into your local net to the server (which does not even know the clien is next to him!). the answers then goes the other way round.

                Note that multiple clients and one server can run on the same machine!

                Qt has to stay free or it will die.

                1 Reply Last reply
                3
                • S Offline
                  S Offline
                  steveq
                  wrote on last edited by
                  #9

                  Hey Guys,

                  Firstly thanks so much for your help.

                  My software is both the server and client in the one package, which now appears to be the source of my problems. In saying that I don’t have the luxury of having a dedicated machine where I can have a server running 24/7. In the future I may look at re-writing my code and have a server running on a Raspberry Pi that I have. If I do that, I guess I’ll need two programs, the chat server and the chat client.

                  In its current form it’s running really well, even allowing multiple clients in the one chat as well as running others chats concurrently. It suits the purpose for which I wrote it, apart from this current issue, which I can “hack” to work if I really want to.

                  From what I understand, the better approach would be where I have a client which connects to a dedicated server and then passes the chat onto the receiving client. All communication then goes through the server.

                  Thanks for everything guys, I really appreciate your help!

                  Steve Q

                  1 Reply Last reply
                  1
                  • KillerSmathK Offline
                    KillerSmathK Offline
                    KillerSmath
                    wrote on last edited by
                    #10

                    @steveq
                    Just as an add-on, you can think of two ways to model a client-server architecture.
                    Centralized and Distributed.
                    Both have their advantages and desvatangens, and all will depend on the purpose of your application.
                    If your application has to provide transparency to the user, whether it is about access (no matter which server I am "connected") or fails (one of the servers is offline), you may have to rethink in a distributed approach.

                    @Computer Science Student - Brazil
                    Web Developer and Researcher
                    “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      steveq
                      wrote on last edited by
                      #11

                      Thanks @KillerSmath, it appears I have a little more reading to do! :-)

                      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