Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: TCP Connection  (Read 9251 times)

0 Members and 4 Guests are viewing this topic.

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: TCP Connection
« Reply #15 on: September 22, 2016, 01:48:14 pm »
This is a Qt project, but since I like how user-friendly the SFML/Network library looks like, I'm using it.

So this is the slot called when the user (server) clicks the "Host" push button. As you can see, it's part of a class named ConnectionInterface, which basically derives from QMainWindow:

void ConnectionInterface::handleHosting(bool checked) const
{
        if (checked) // When you click it or when HostButton->setChecked(true) is called
        {
                if (NS::GameListener.listen(38956) != sf::Socket::Done)
                {
                        QMessageBox::critical(MainWidget, "Err", "Could not listen to port.");
                        HostButton->setChecked(false);
                }
                else
                {
                        NS::GameListener.setBlocking(false);
                        NS::GameListener.accept(NS::GamingSocket);
                        HostButton->setText("Hosting...");
               
                        QObject::connect(&GS::RoutineNetworkingTimer, SIGNAL(timeout(void)), const_cast<ConnectionInterface*>(this), SLOT(hostingRoutineFunction(void)));
                        GS::RoutineNetworkingTimer.start(GS::MinimalNetworkingPeriod);
                }
        }
        else // When you unclick it or when HostButton->setChecked(false) is called, but that never happens
        {
                NS::GameListener.close();
                NS::GamingSocket.disconnect();
                HostButton->setText("Host");
                NS::GameListener.setBlocking(true);

                GS::RoutineNetworkingTimer.stop();
                QObject::disconnect(&GS::RoutineNetworkingTimer, SIGNAL(timeout(void)), const_cast<ConnectionInterface*>(this), SLOT(hostingRoutineFunction(void)));
        }
}

Then ConnectionInterface::hostingRoutineFunction is called every 10 ms, until the sf::TcpSocket is accepted by the sf::TcpListener.

void ConnectionInterface::hostingRoutineFunction(void) const
{
        if (NS::GameListener.accept(NS::GamingSocket) != sf::Socket::Done)
                return;
       
        GS::RoutineNetworkingTimer.stop();
        QObject::disconnect(&GS::RoutineNetworkingTimer, SIGNAL(timeout(void)), const_cast<ConnectionInterface*>(this), SLOT(hostingRoutineFunction(void)));
       
        QObject::connect(&GS::RoutineNetworkingTimer, SIGNAL(timeout(void)), const_cast<ConnectionInterface*>(this), SLOT(gameRoutineFunction(void)));
        GS::RoutineNetworkingTimer.start(GS::MinimalNetworkingPeriod);

        // Do game-related, network-unrelated stuff
}

Then that function doesn't need to be called anymore, and we can move onto the function that is receiving packets over and over until the connection is closed / until the game is over. And this is what that function (ConnectionInterface::gameRoutineFunction) looks like:

void ConnectionInterface::gameRoutineFunction(void) const
{
        if ((NS::LastReceivingStatus == sf::Socket::Status::Partial && GS::PendingPacket) || not GS::PendingPacket)
        {
                NS::LastReceivingStatus = NS::GamingSocket.receive(NS::ReceivingPacket);
                GS::PendingPacket = (NS::ReceivingPacket.getDataSize() > 0);
        }
       
        if (GS::PendingPacket && NS::LastReceivingStatus == sf::Socket::Status::Done)
        {
                // and we never get there, for GS::PendingPacket is always false...
                // (while NS::LastReceivingStatus is always equal to sf::Socket::Status::NotReady)
        }
}

I'm glad you didn't ask me to see what the other side looks like ^^
« Last Edit: September 22, 2016, 01:53:00 pm by Law »

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: TCP Connection
« Reply #16 on: September 23, 2016, 10:27:29 am »
Okay, the fact that nobody seemed to find anything wrong in my code made me think it was completely operational, so I started to focus on other things... and it turned out the problem had nothing to do with the network framework. I do apologize so terribly...

If you're interested in the reason things were failing miserably, here's why. I have an enum.

enum Message : quint8   {
                                // ...
                                Join                                    = 15,
                                // ...
                                };

and the first packet that is to be sent in my project is a packet with Enum::Message::Join inside. So here's what I did:

NS::SendingPacket.clear();
NS::SendingPacket << Enum::Message::Join << // other stuff

But when unpacking, I was always reading 0 (instead of 15)... The following code fixed everything:

NS::SendingPacket.clear();
NS::SendingPacket << static_cast<quint8>(Enum::Message::Join) << // other stuff

So there you have it. I'm surprised I had to cast it, but as long as my code works I suppose it doesn't matter. Thank you again, all of you :)