Search code examples
c++sfml

Sfml networking, SocketSelector member function isReady not working correctly


I am coding simple networking system based on sfml-network liblary and tcp sockets. When i compile and run my program i am getting that output on screen(screenshot). screenshot

It looks like selector.wait() (Server.cpp:20) is not waiting for any packet and selector.isReady(TCPSOCKET) (Server.cpp:43) is not checking correctly if client is sending package to server.

Code: main.cpp

#include <iostream>
#include "Server.h"

int main()
{
    int mode = 0;
    std::cin >> mode;
    if(mode == 0)
    {
        Server server(55200);
    }else if(mode == 1){

        sf::TcpSocket socket;

        if (socket.connect("localhost", 55200) != sf::Socket::Done)
        {
            std::cout << "Error1\n";
        }
        //Sleep(2000);
        sf::Packet packet;
        packet << 11;
        if (socket.send(packet) != sf::Socket::Done)
        {
            std::cout << "Error2\n";
        }


    }
    std::cin.get();
    std::cin.get();
}

Server.h

#pragma once
#include <SFML/Network.hpp>
#include <vector>
class Server
{
private:
    sf::TcpListener listener;
    std::vector<sf::TcpSocket*> clients;
    sf::SocketSelector selector;
    unsigned short port;
public:
    Server(unsigned short port);
    ~Server();
};

Server.cpp

#include "Server.h"
#include <iostream>
#include <SFML/Network.hpp>
#include <vector>

Server::Server(unsigned short pport)
{
    port = pport;
    std::cout << "Starting Server....\n";
    if (listener.listen(port) != sf::Socket::Done)
    {
        std::cout << "Failed while starting listening on port: " << port << std::endl;
        return;
    }

    selector.add(listener);

    while(true)
    {
        if (selector.wait())
        {

            //new connection
            if (selector.isReady(listener))
            {
                std::cout << "New connection!!\n";
                sf::TcpSocket* tmp = new sf::TcpSocket; // !!!!!!!!!!!
                if (listener.accept(*tmp) != sf::Socket::Done)
                {
                    std::cout << "Error while accepting new connection\n";
                    delete tmp;
                }
                else {
                    selector.add(*tmp);
                    clients.push_back(tmp);
                }
            }
            else {

                for (int i = 0; i < clients.size(); i++)
                {
                    //new incoming packet
                    if(selector.isReady(*(clients[i])))
                    {
                        sf::Packet pakiet;
                        if (clients[i]->receive(pakiet) != sf::Socket::Done)
                        {
                            std::cout << "Error while receiving packet\n";
                        }
                        else {
                            int x;
                            pakiet >> x;
                            std::cout << "Recived new data!!!: " << x << std::endl;
                        }
                    }
                }
            }
        }
    }
}

Server::~Server()
{
    for (int i = 0; i < clients.size();i++)
    {
        delete clients[i];
    }
}

Solution

  • You created a client which connected to the server, sent one package and at the end of the scope was destroyed. Socket at the client side doesn't exist and the connection between client-server is closed. So, how do you want to get the information about closed connection at server side ?

    Function isReady returns true, then you call receive for this socket and as output you get one of Status codes: Done, NotReady, Disconnected, Error. You need to check if status is Disconnected, if so, the client socket should be removed from selector.

      if(selector.isReady(*(clients[i])))
      {
          sf::Packet pakiet;
          if ( clients[i]->receive(pakiet) == sf::Socket::Done)
          {
              // process data
          }
          else if ( clients[i]->receive(pakiet) == sf::Socket::Disconnected ) {
               // delete socket, remove from selector
          }
          else {
             // 
          }
      }