SFML Detect multiple connections to server and count them












0















I'm creating a very simple client/server application.
I want my server to detect how many clients have connected and if there are more than 2, just print a message.



The code for the server I have so far is very minimal:



std::vector<sf::TcpSocket*> clients;

sf::TcpListener listener;

if (listener.listen(SERVERPORT) != sf::Socket::Done)
{
printf("Errorn");
}

printf("Waiting for first connection...n");

sf::TcpSocket *socket = new sf::TcpSocket;

if (listener.accept(*socket) != sf::Socket::Done)
{
printf("Errorn");
}

clients.push_back(socket);

while (clients.size() < 2)
{
printf("Waiting for second connection...n");
}


The problem I have is that it detects the first connection with no problem, but it doesn't detect the second one, even though my second client is connected. For the client connection I'm just using the very simple code explained in the SFML documentation.
I'm very confused as clients.size() always returns 1.










share|improve this question



























    0















    I'm creating a very simple client/server application.
    I want my server to detect how many clients have connected and if there are more than 2, just print a message.



    The code for the server I have so far is very minimal:



    std::vector<sf::TcpSocket*> clients;

    sf::TcpListener listener;

    if (listener.listen(SERVERPORT) != sf::Socket::Done)
    {
    printf("Errorn");
    }

    printf("Waiting for first connection...n");

    sf::TcpSocket *socket = new sf::TcpSocket;

    if (listener.accept(*socket) != sf::Socket::Done)
    {
    printf("Errorn");
    }

    clients.push_back(socket);

    while (clients.size() < 2)
    {
    printf("Waiting for second connection...n");
    }


    The problem I have is that it detects the first connection with no problem, but it doesn't detect the second one, even though my second client is connected. For the client connection I'm just using the very simple code explained in the SFML documentation.
    I'm very confused as clients.size() always returns 1.










    share|improve this question

























      0












      0








      0








      I'm creating a very simple client/server application.
      I want my server to detect how many clients have connected and if there are more than 2, just print a message.



      The code for the server I have so far is very minimal:



      std::vector<sf::TcpSocket*> clients;

      sf::TcpListener listener;

      if (listener.listen(SERVERPORT) != sf::Socket::Done)
      {
      printf("Errorn");
      }

      printf("Waiting for first connection...n");

      sf::TcpSocket *socket = new sf::TcpSocket;

      if (listener.accept(*socket) != sf::Socket::Done)
      {
      printf("Errorn");
      }

      clients.push_back(socket);

      while (clients.size() < 2)
      {
      printf("Waiting for second connection...n");
      }


      The problem I have is that it detects the first connection with no problem, but it doesn't detect the second one, even though my second client is connected. For the client connection I'm just using the very simple code explained in the SFML documentation.
      I'm very confused as clients.size() always returns 1.










      share|improve this question














      I'm creating a very simple client/server application.
      I want my server to detect how many clients have connected and if there are more than 2, just print a message.



      The code for the server I have so far is very minimal:



      std::vector<sf::TcpSocket*> clients;

      sf::TcpListener listener;

      if (listener.listen(SERVERPORT) != sf::Socket::Done)
      {
      printf("Errorn");
      }

      printf("Waiting for first connection...n");

      sf::TcpSocket *socket = new sf::TcpSocket;

      if (listener.accept(*socket) != sf::Socket::Done)
      {
      printf("Errorn");
      }

      clients.push_back(socket);

      while (clients.size() < 2)
      {
      printf("Waiting for second connection...n");
      }


      The problem I have is that it detects the first connection with no problem, but it doesn't detect the second one, even though my second client is connected. For the client connection I'm just using the very simple code explained in the SFML documentation.
      I'm very confused as clients.size() always returns 1.







      c++ sockets networking sfml






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 23 '18 at 14:04









      Koosshh56Koosshh56

      1578




      1578
























          1 Answer
          1






          active

          oldest

          votes


















          0














          Because you don't accept a second connection...



          Changing code order a little:



          std::vector<sf::TcpSocket*> clients;

          sf::TcpListener listener;

          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          printf("Waiting for first connection...n");

          while (clients.size() < 2)
          {
          sf::TcpSocket *socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          clients.push_back(socket);

          // OK, that one would be printed twice!!!
          printf("Waiting for second connection...n");
          }


          This won't be the final loop, though, it is just intended for demonstration.



          Be aware that you don't delete the clients created anywhere (-> memory leak!). You might consider usage of smart pointers instead of raw pointers.



          OK, so now: you want to accept arbitrary number of clients, and as soon as number you have more than two clients, run some application.



          At very first, you need to continue accepting new clients on the loop (I changed the logging messages a little...:



          std::vector<sf::TcpSocket*> clients;
          sf::TcpListener listener;
          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          return; // no need to go on on error!
          }

          printf("start waiting for clients...n");

          for(;;) // endless loop...
          {
          sf::TcpSocket* socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          // TODO: consider some appropriate error handling
          // minimally:
          delete socket; // otherwise, you produce memory leaks!
          }

          clients.push_back(socket);
          printf
          (
          "new client accepted; number of clients now: %llun"
          "continue waiting...n",
          clients.size()
          );
          // llu: most likely on 64-bit machine, on 32 bit either lu or u,
          // depending on type of size_t; you get around having to decide
          // if using C++ streams instead...
          }


          Problem now is: You additionally need to handle the connections appropriately! Have a look at this SFML tutorial, especially the section Blocking on a group of sockets. The selector described there is exactly what you need. Most important:




          A selector can monitor all types of sockets: sf::TcpSocket, sf::UdpSocket, and sf::TcpListener.




          So you can add all of your sockets and the listener to. You still have to maintain your instances yourself, though:




          A selector is not a socket container. It only references (points to) the sockets that you add, it doesn't store them. There is no way to retrieve or count the sockets that you put inside. Instead, [...].




          Well, you covered the 'instead' part already with your vector. Normally I'd recommend storing the objects in the vector directly; however, you cannot, as you need references to in the selector. So you need to store pointers in the vector – or you can use a std::list instead, which won't invalidate references or pointers to stored data on insertion or deletion of objects (apart from pointers to the removed object itself, of course).



          If you want to stay with the vector, you might consider using smart pointers, though, so that you don't have to care for memory management (e. g. std::vector<std::unique_ptr<sf::TcpSocket>> clients).



          I personally would prefer the std::list:



          std::list<sf::TcpSocket> clients; // notice: no pointers...
          sf::TcpListener listener;
          sf::SocketSelector selector;
          selector.add(listener); // you want to listen as well...
          for(;;)
          {
          // wait on selector as described in tutorial, I'd recommend only
          // waiting for one second: you might want to handle the application
          // exiting at some point of time!
          }


          If waiting was successful, you'd now first check the server socket, then the clients):



          if(listener.isReady())
          {
          // OK, we now know that a client is waiting, so next steps won't block:
          clients.emplace_back(); // new client
          if(listener.accept(clients.back()) != sf::Socket::Done)
          {
          // OK, something went wrong, current client us valueless...
          clients.pop_back();
          // adding and then removing? well, normally, this case here
          // should not occur anyway, so we optimized for the far more
          // common case.
          }
          else
          {
          // want to listen on as well
          selector.add(clients.back());
          }
          }
          for(auto& c : clients)
          {
          if(c.isReady())
          {
          // handle communication
          }
          }


          Handling communinication is up to you... I wouldn't just communicate if at least two clients are connected. If you leave the messages from one single client unhandled, you might end up in needing to handle quite a bunch of outdated messages as soon as another client arrives, so I'd rather handle anything incoming immediately even with one single client. If it appears more appropriate to you, you might still place a if(clients.size() >= 2) around the (range based) for loop.



          If a client disconnects, don't forget to remove it from the selector! Having done so, you can safely remove it from the clients list as well.



          Finally: the endless loop!



          You might want to replace this via some conditional loop, checking if the server should still be running at all or not. You'd then yet need some mechanism to set this condition to false. There are different options for, e. g. some separate thread checking some specific input, signals (especially on POSIX systems), ...






          share|improve this answer


























          • I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

            – Koosshh56
            Nov 23 '18 at 14:49













          • Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

            – Koosshh56
            Nov 23 '18 at 14:55











          • any help with this? I'm still stuck. Thanks

            – Koosshh56
            Nov 26 '18 at 9:19













          • @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

            – Aconcagua
            Nov 26 '18 at 11:18













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448141%2fsfml-detect-multiple-connections-to-server-and-count-them%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          Because you don't accept a second connection...



          Changing code order a little:



          std::vector<sf::TcpSocket*> clients;

          sf::TcpListener listener;

          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          printf("Waiting for first connection...n");

          while (clients.size() < 2)
          {
          sf::TcpSocket *socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          clients.push_back(socket);

          // OK, that one would be printed twice!!!
          printf("Waiting for second connection...n");
          }


          This won't be the final loop, though, it is just intended for demonstration.



          Be aware that you don't delete the clients created anywhere (-> memory leak!). You might consider usage of smart pointers instead of raw pointers.



          OK, so now: you want to accept arbitrary number of clients, and as soon as number you have more than two clients, run some application.



          At very first, you need to continue accepting new clients on the loop (I changed the logging messages a little...:



          std::vector<sf::TcpSocket*> clients;
          sf::TcpListener listener;
          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          return; // no need to go on on error!
          }

          printf("start waiting for clients...n");

          for(;;) // endless loop...
          {
          sf::TcpSocket* socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          // TODO: consider some appropriate error handling
          // minimally:
          delete socket; // otherwise, you produce memory leaks!
          }

          clients.push_back(socket);
          printf
          (
          "new client accepted; number of clients now: %llun"
          "continue waiting...n",
          clients.size()
          );
          // llu: most likely on 64-bit machine, on 32 bit either lu or u,
          // depending on type of size_t; you get around having to decide
          // if using C++ streams instead...
          }


          Problem now is: You additionally need to handle the connections appropriately! Have a look at this SFML tutorial, especially the section Blocking on a group of sockets. The selector described there is exactly what you need. Most important:




          A selector can monitor all types of sockets: sf::TcpSocket, sf::UdpSocket, and sf::TcpListener.




          So you can add all of your sockets and the listener to. You still have to maintain your instances yourself, though:




          A selector is not a socket container. It only references (points to) the sockets that you add, it doesn't store them. There is no way to retrieve or count the sockets that you put inside. Instead, [...].




          Well, you covered the 'instead' part already with your vector. Normally I'd recommend storing the objects in the vector directly; however, you cannot, as you need references to in the selector. So you need to store pointers in the vector – or you can use a std::list instead, which won't invalidate references or pointers to stored data on insertion or deletion of objects (apart from pointers to the removed object itself, of course).



          If you want to stay with the vector, you might consider using smart pointers, though, so that you don't have to care for memory management (e. g. std::vector<std::unique_ptr<sf::TcpSocket>> clients).



          I personally would prefer the std::list:



          std::list<sf::TcpSocket> clients; // notice: no pointers...
          sf::TcpListener listener;
          sf::SocketSelector selector;
          selector.add(listener); // you want to listen as well...
          for(;;)
          {
          // wait on selector as described in tutorial, I'd recommend only
          // waiting for one second: you might want to handle the application
          // exiting at some point of time!
          }


          If waiting was successful, you'd now first check the server socket, then the clients):



          if(listener.isReady())
          {
          // OK, we now know that a client is waiting, so next steps won't block:
          clients.emplace_back(); // new client
          if(listener.accept(clients.back()) != sf::Socket::Done)
          {
          // OK, something went wrong, current client us valueless...
          clients.pop_back();
          // adding and then removing? well, normally, this case here
          // should not occur anyway, so we optimized for the far more
          // common case.
          }
          else
          {
          // want to listen on as well
          selector.add(clients.back());
          }
          }
          for(auto& c : clients)
          {
          if(c.isReady())
          {
          // handle communication
          }
          }


          Handling communinication is up to you... I wouldn't just communicate if at least two clients are connected. If you leave the messages from one single client unhandled, you might end up in needing to handle quite a bunch of outdated messages as soon as another client arrives, so I'd rather handle anything incoming immediately even with one single client. If it appears more appropriate to you, you might still place a if(clients.size() >= 2) around the (range based) for loop.



          If a client disconnects, don't forget to remove it from the selector! Having done so, you can safely remove it from the clients list as well.



          Finally: the endless loop!



          You might want to replace this via some conditional loop, checking if the server should still be running at all or not. You'd then yet need some mechanism to set this condition to false. There are different options for, e. g. some separate thread checking some specific input, signals (especially on POSIX systems), ...






          share|improve this answer


























          • I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

            – Koosshh56
            Nov 23 '18 at 14:49













          • Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

            – Koosshh56
            Nov 23 '18 at 14:55











          • any help with this? I'm still stuck. Thanks

            – Koosshh56
            Nov 26 '18 at 9:19













          • @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

            – Aconcagua
            Nov 26 '18 at 11:18


















          0














          Because you don't accept a second connection...



          Changing code order a little:



          std::vector<sf::TcpSocket*> clients;

          sf::TcpListener listener;

          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          printf("Waiting for first connection...n");

          while (clients.size() < 2)
          {
          sf::TcpSocket *socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          clients.push_back(socket);

          // OK, that one would be printed twice!!!
          printf("Waiting for second connection...n");
          }


          This won't be the final loop, though, it is just intended for demonstration.



          Be aware that you don't delete the clients created anywhere (-> memory leak!). You might consider usage of smart pointers instead of raw pointers.



          OK, so now: you want to accept arbitrary number of clients, and as soon as number you have more than two clients, run some application.



          At very first, you need to continue accepting new clients on the loop (I changed the logging messages a little...:



          std::vector<sf::TcpSocket*> clients;
          sf::TcpListener listener;
          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          return; // no need to go on on error!
          }

          printf("start waiting for clients...n");

          for(;;) // endless loop...
          {
          sf::TcpSocket* socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          // TODO: consider some appropriate error handling
          // minimally:
          delete socket; // otherwise, you produce memory leaks!
          }

          clients.push_back(socket);
          printf
          (
          "new client accepted; number of clients now: %llun"
          "continue waiting...n",
          clients.size()
          );
          // llu: most likely on 64-bit machine, on 32 bit either lu or u,
          // depending on type of size_t; you get around having to decide
          // if using C++ streams instead...
          }


          Problem now is: You additionally need to handle the connections appropriately! Have a look at this SFML tutorial, especially the section Blocking on a group of sockets. The selector described there is exactly what you need. Most important:




          A selector can monitor all types of sockets: sf::TcpSocket, sf::UdpSocket, and sf::TcpListener.




          So you can add all of your sockets and the listener to. You still have to maintain your instances yourself, though:




          A selector is not a socket container. It only references (points to) the sockets that you add, it doesn't store them. There is no way to retrieve or count the sockets that you put inside. Instead, [...].




          Well, you covered the 'instead' part already with your vector. Normally I'd recommend storing the objects in the vector directly; however, you cannot, as you need references to in the selector. So you need to store pointers in the vector – or you can use a std::list instead, which won't invalidate references or pointers to stored data on insertion or deletion of objects (apart from pointers to the removed object itself, of course).



          If you want to stay with the vector, you might consider using smart pointers, though, so that you don't have to care for memory management (e. g. std::vector<std::unique_ptr<sf::TcpSocket>> clients).



          I personally would prefer the std::list:



          std::list<sf::TcpSocket> clients; // notice: no pointers...
          sf::TcpListener listener;
          sf::SocketSelector selector;
          selector.add(listener); // you want to listen as well...
          for(;;)
          {
          // wait on selector as described in tutorial, I'd recommend only
          // waiting for one second: you might want to handle the application
          // exiting at some point of time!
          }


          If waiting was successful, you'd now first check the server socket, then the clients):



          if(listener.isReady())
          {
          // OK, we now know that a client is waiting, so next steps won't block:
          clients.emplace_back(); // new client
          if(listener.accept(clients.back()) != sf::Socket::Done)
          {
          // OK, something went wrong, current client us valueless...
          clients.pop_back();
          // adding and then removing? well, normally, this case here
          // should not occur anyway, so we optimized for the far more
          // common case.
          }
          else
          {
          // want to listen on as well
          selector.add(clients.back());
          }
          }
          for(auto& c : clients)
          {
          if(c.isReady())
          {
          // handle communication
          }
          }


          Handling communinication is up to you... I wouldn't just communicate if at least two clients are connected. If you leave the messages from one single client unhandled, you might end up in needing to handle quite a bunch of outdated messages as soon as another client arrives, so I'd rather handle anything incoming immediately even with one single client. If it appears more appropriate to you, you might still place a if(clients.size() >= 2) around the (range based) for loop.



          If a client disconnects, don't forget to remove it from the selector! Having done so, you can safely remove it from the clients list as well.



          Finally: the endless loop!



          You might want to replace this via some conditional loop, checking if the server should still be running at all or not. You'd then yet need some mechanism to set this condition to false. There are different options for, e. g. some separate thread checking some specific input, signals (especially on POSIX systems), ...






          share|improve this answer


























          • I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

            – Koosshh56
            Nov 23 '18 at 14:49













          • Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

            – Koosshh56
            Nov 23 '18 at 14:55











          • any help with this? I'm still stuck. Thanks

            – Koosshh56
            Nov 26 '18 at 9:19













          • @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

            – Aconcagua
            Nov 26 '18 at 11:18
















          0












          0








          0







          Because you don't accept a second connection...



          Changing code order a little:



          std::vector<sf::TcpSocket*> clients;

          sf::TcpListener listener;

          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          printf("Waiting for first connection...n");

          while (clients.size() < 2)
          {
          sf::TcpSocket *socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          clients.push_back(socket);

          // OK, that one would be printed twice!!!
          printf("Waiting for second connection...n");
          }


          This won't be the final loop, though, it is just intended for demonstration.



          Be aware that you don't delete the clients created anywhere (-> memory leak!). You might consider usage of smart pointers instead of raw pointers.



          OK, so now: you want to accept arbitrary number of clients, and as soon as number you have more than two clients, run some application.



          At very first, you need to continue accepting new clients on the loop (I changed the logging messages a little...:



          std::vector<sf::TcpSocket*> clients;
          sf::TcpListener listener;
          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          return; // no need to go on on error!
          }

          printf("start waiting for clients...n");

          for(;;) // endless loop...
          {
          sf::TcpSocket* socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          // TODO: consider some appropriate error handling
          // minimally:
          delete socket; // otherwise, you produce memory leaks!
          }

          clients.push_back(socket);
          printf
          (
          "new client accepted; number of clients now: %llun"
          "continue waiting...n",
          clients.size()
          );
          // llu: most likely on 64-bit machine, on 32 bit either lu or u,
          // depending on type of size_t; you get around having to decide
          // if using C++ streams instead...
          }


          Problem now is: You additionally need to handle the connections appropriately! Have a look at this SFML tutorial, especially the section Blocking on a group of sockets. The selector described there is exactly what you need. Most important:




          A selector can monitor all types of sockets: sf::TcpSocket, sf::UdpSocket, and sf::TcpListener.




          So you can add all of your sockets and the listener to. You still have to maintain your instances yourself, though:




          A selector is not a socket container. It only references (points to) the sockets that you add, it doesn't store them. There is no way to retrieve or count the sockets that you put inside. Instead, [...].




          Well, you covered the 'instead' part already with your vector. Normally I'd recommend storing the objects in the vector directly; however, you cannot, as you need references to in the selector. So you need to store pointers in the vector – or you can use a std::list instead, which won't invalidate references or pointers to stored data on insertion or deletion of objects (apart from pointers to the removed object itself, of course).



          If you want to stay with the vector, you might consider using smart pointers, though, so that you don't have to care for memory management (e. g. std::vector<std::unique_ptr<sf::TcpSocket>> clients).



          I personally would prefer the std::list:



          std::list<sf::TcpSocket> clients; // notice: no pointers...
          sf::TcpListener listener;
          sf::SocketSelector selector;
          selector.add(listener); // you want to listen as well...
          for(;;)
          {
          // wait on selector as described in tutorial, I'd recommend only
          // waiting for one second: you might want to handle the application
          // exiting at some point of time!
          }


          If waiting was successful, you'd now first check the server socket, then the clients):



          if(listener.isReady())
          {
          // OK, we now know that a client is waiting, so next steps won't block:
          clients.emplace_back(); // new client
          if(listener.accept(clients.back()) != sf::Socket::Done)
          {
          // OK, something went wrong, current client us valueless...
          clients.pop_back();
          // adding and then removing? well, normally, this case here
          // should not occur anyway, so we optimized for the far more
          // common case.
          }
          else
          {
          // want to listen on as well
          selector.add(clients.back());
          }
          }
          for(auto& c : clients)
          {
          if(c.isReady())
          {
          // handle communication
          }
          }


          Handling communinication is up to you... I wouldn't just communicate if at least two clients are connected. If you leave the messages from one single client unhandled, you might end up in needing to handle quite a bunch of outdated messages as soon as another client arrives, so I'd rather handle anything incoming immediately even with one single client. If it appears more appropriate to you, you might still place a if(clients.size() >= 2) around the (range based) for loop.



          If a client disconnects, don't forget to remove it from the selector! Having done so, you can safely remove it from the clients list as well.



          Finally: the endless loop!



          You might want to replace this via some conditional loop, checking if the server should still be running at all or not. You'd then yet need some mechanism to set this condition to false. There are different options for, e. g. some separate thread checking some specific input, signals (especially on POSIX systems), ...






          share|improve this answer















          Because you don't accept a second connection...



          Changing code order a little:



          std::vector<sf::TcpSocket*> clients;

          sf::TcpListener listener;

          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          printf("Waiting for first connection...n");

          while (clients.size() < 2)
          {
          sf::TcpSocket *socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          }

          clients.push_back(socket);

          // OK, that one would be printed twice!!!
          printf("Waiting for second connection...n");
          }


          This won't be the final loop, though, it is just intended for demonstration.



          Be aware that you don't delete the clients created anywhere (-> memory leak!). You might consider usage of smart pointers instead of raw pointers.



          OK, so now: you want to accept arbitrary number of clients, and as soon as number you have more than two clients, run some application.



          At very first, you need to continue accepting new clients on the loop (I changed the logging messages a little...:



          std::vector<sf::TcpSocket*> clients;
          sf::TcpListener listener;
          if (listener.listen(SERVERPORT) != sf::Socket::Done)
          {
          printf("Errorn");
          return; // no need to go on on error!
          }

          printf("start waiting for clients...n");

          for(;;) // endless loop...
          {
          sf::TcpSocket* socket = new sf::TcpSocket;
          if (listener.accept(*socket) != sf::Socket::Done)
          {
          printf("Errorn");
          // TODO: consider some appropriate error handling
          // minimally:
          delete socket; // otherwise, you produce memory leaks!
          }

          clients.push_back(socket);
          printf
          (
          "new client accepted; number of clients now: %llun"
          "continue waiting...n",
          clients.size()
          );
          // llu: most likely on 64-bit machine, on 32 bit either lu or u,
          // depending on type of size_t; you get around having to decide
          // if using C++ streams instead...
          }


          Problem now is: You additionally need to handle the connections appropriately! Have a look at this SFML tutorial, especially the section Blocking on a group of sockets. The selector described there is exactly what you need. Most important:




          A selector can monitor all types of sockets: sf::TcpSocket, sf::UdpSocket, and sf::TcpListener.




          So you can add all of your sockets and the listener to. You still have to maintain your instances yourself, though:




          A selector is not a socket container. It only references (points to) the sockets that you add, it doesn't store them. There is no way to retrieve or count the sockets that you put inside. Instead, [...].




          Well, you covered the 'instead' part already with your vector. Normally I'd recommend storing the objects in the vector directly; however, you cannot, as you need references to in the selector. So you need to store pointers in the vector – or you can use a std::list instead, which won't invalidate references or pointers to stored data on insertion or deletion of objects (apart from pointers to the removed object itself, of course).



          If you want to stay with the vector, you might consider using smart pointers, though, so that you don't have to care for memory management (e. g. std::vector<std::unique_ptr<sf::TcpSocket>> clients).



          I personally would prefer the std::list:



          std::list<sf::TcpSocket> clients; // notice: no pointers...
          sf::TcpListener listener;
          sf::SocketSelector selector;
          selector.add(listener); // you want to listen as well...
          for(;;)
          {
          // wait on selector as described in tutorial, I'd recommend only
          // waiting for one second: you might want to handle the application
          // exiting at some point of time!
          }


          If waiting was successful, you'd now first check the server socket, then the clients):



          if(listener.isReady())
          {
          // OK, we now know that a client is waiting, so next steps won't block:
          clients.emplace_back(); // new client
          if(listener.accept(clients.back()) != sf::Socket::Done)
          {
          // OK, something went wrong, current client us valueless...
          clients.pop_back();
          // adding and then removing? well, normally, this case here
          // should not occur anyway, so we optimized for the far more
          // common case.
          }
          else
          {
          // want to listen on as well
          selector.add(clients.back());
          }
          }
          for(auto& c : clients)
          {
          if(c.isReady())
          {
          // handle communication
          }
          }


          Handling communinication is up to you... I wouldn't just communicate if at least two clients are connected. If you leave the messages from one single client unhandled, you might end up in needing to handle quite a bunch of outdated messages as soon as another client arrives, so I'd rather handle anything incoming immediately even with one single client. If it appears more appropriate to you, you might still place a if(clients.size() >= 2) around the (range based) for loop.



          If a client disconnects, don't forget to remove it from the selector! Having done so, you can safely remove it from the clients list as well.



          Finally: the endless loop!



          You might want to replace this via some conditional loop, checking if the server should still be running at all or not. You'd then yet need some mechanism to set this condition to false. There are different options for, e. g. some separate thread checking some specific input, signals (especially on POSIX systems), ...







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 26 '18 at 11:25

























          answered Nov 23 '18 at 14:27









          AconcaguaAconcagua

          12.3k32143




          12.3k32143













          • I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

            – Koosshh56
            Nov 23 '18 at 14:49













          • Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

            – Koosshh56
            Nov 23 '18 at 14:55











          • any help with this? I'm still stuck. Thanks

            – Koosshh56
            Nov 26 '18 at 9:19













          • @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

            – Aconcagua
            Nov 26 '18 at 11:18





















          • I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

            – Koosshh56
            Nov 23 '18 at 14:49













          • Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

            – Koosshh56
            Nov 23 '18 at 14:55











          • any help with this? I'm still stuck. Thanks

            – Koosshh56
            Nov 26 '18 at 9:19













          • @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

            – Aconcagua
            Nov 26 '18 at 11:18



















          I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

          – Koosshh56
          Nov 23 '18 at 14:49







          I've just tried your first solution and it's not really working. When I connect the first client, client.size() is equal to 2, even if I haven't connected my second client yet. Also, I don' really want exactly 2 clients, but at least 2...if that makes sense. It will be a matchmaking system...

          – Koosshh56
          Nov 23 '18 at 14:49















          Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

          – Koosshh56
          Nov 23 '18 at 14:55





          Also, I tried to increase the while condition threshold clients.size() < 2 to 10, and it counts one connection as 3...so the clients.size() increases by 3 every time I connect a client

          – Koosshh56
          Nov 23 '18 at 14:55













          any help with this? I'm still stuck. Thanks

          – Koosshh56
          Nov 26 '18 at 9:19







          any help with this? I'm still stuck. Thanks

          – Koosshh56
          Nov 26 '18 at 9:19















          @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

          – Aconcagua
          Nov 26 '18 at 11:18







          @Koosshh56 Without seing your changed code, a bit difficult to guess the issues... I modified this answer, though, so it (hopefully) covers your needs better.

          – Aconcagua
          Nov 26 '18 at 11:18






















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448141%2fsfml-detect-multiple-connections-to-server-and-count-them%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Wiesbaden

          Marschland

          Dieringhausen