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 ^^