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

Author Topic: Multiple clients connecting to one server  (Read 6308 times)

0 Members and 1 Guest are viewing this topic.

Ninjaboi

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • http://www.ninjasoftcorp.webs.com/index.html
Multiple clients connecting to one server
« on: May 29, 2014, 10:09:37 pm »
This may enter the realm of stupidity here but I wanted to make sure I'm understanding the tutorial for SFML 2.1's Networking module. The example code and accompanying text skims over how two or more triggering connections are handled using sf::Sockets. My understanding was that, if I had a TCP server-client relation program, the server would need one listener socket for incoming connections and one socket for every client that connects. This seems to be exactly what this line in the tutorial states:

Quote
On server side, more things need to be done. Multiple sockets are required: one that listens for incoming connections, and one for each connected client.

The code in the example however only provides the example for the situation of having only one server and one client connecting at a time as far as I can tell:

sf::TcpListener listener;

// bind the listener to a port
if (listener.listen(53000) != sf::Socket::Done)
{
    // error...
}

// accept a new connection
sf::TcpSocket client;
if (listener.accept(client) != sf::Socket::Done)
{
    // error...
}

// use "client" to communicate with the connected client,
// and continue to accept new connections with the listener

As I have understood it ( and the comments at the bottom of the tutorial code states this ), all I need is for the clients to know where to find the listener socket ( IP address and port it's listening from ) then the listener will accept the connection and return a successfully connected client in a sf::Socket of my choice to handle all further interactions with this unique client until they disconnect thus freeing the socket for a new client.

Going with my logic flow earlier I figured all I need to do is if I want say five clients to be able to be connected to the server all at the same time then I need six sockets; one to listen for new connections and one to handle the transfer of information to and from each client ( so five of these as this example wants five clients ). So my code might at first look like this:

sf::TcpListener listener;

// bind the listener to a port
if (listener.listen(53000) != sf::Socket::Done)
{
    // error...
}

while(running)
{

// accept a new connection
sf::TcpSocket client1;
sf::TcpSocket client2;
sf::TcpSocket client3;
sf::TcpSocket client4;
sf::TcpSocket client5;

// Check to see if client1 is being used and if not give the new client this socket.
if(client1 == openForNewClient)
{
    if (listener.accept(client1) != sf::Socket::Done)
    {
        // error...
    }
}else
// Check to see if client2 is being used and if not give the new client this socket.
if(client2 == openForNewClient)
{
    if (listener.accept(client2) != sf::Socket::Done)
    {
        // error...
    }
}else
// Check to see if client3 is being used and if not give the new client this socket.
if(client3 == openForNewClient)
{
    if (listener.accept(client3) != sf::Socket::Done)
    {
        // error...
    }
}else
// Check to see if client4 is being used and if not give the new client this socket.
if(client4 == openForNewClient)
{
    if (listener.accept(client4) != sf::Socket::Done)
    {
        // error...
    }
}else
// Check to see if client5 is being used and if not give the new client this socket.
if(client5 == openForNewClient)
{
    if (listener.accept(client5) != sf::Socket::Done)
    {
        // error...
    }
}else
{
    // Inform potential client that there is no slot ( socket ) available.
    // The client doesn't connect.
}

// See if client1 is sending data or needs data sent.
// See if client2 is sending data or needs data sent.
// See if client3 is sending data or needs data sent.
// See if client4 is sending data or needs data sent.
// See if client5 is sending data or needs data sent.

// Update server's local frame of information based on what was received by clients.

// See if client1 has disconnected and therefore has freed the socket they were using.
// See if client2 has disconnected and therefore has freed the socket they were using.
// See if client3 has disconnected and therefore has freed the socket they were using.
// See if client4 has disconnected and therefore has freed the socket they were using.
// See if client5 has disconnected and therefore has freed the socket they were using.
}

Basically I want to know how to determine if a socket is in use by a client so that I can let my listening socket assign them with the correct socket. If there's no socket available then they simply don't connect. However sf::Socket::Status doesn't have a "In-use" enum, but I figured that's what "NotReady" was for. Am I right and would checking the status for "NotReady" being true determine whether a socket is in use by another client or not? Am I missing something obvious here? Is the "Disconnected" enum not just for the action of closing one of the two connected sockets from either the client or server?

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Multiple clients connecting to one server
« Reply #1 on: May 30, 2014, 06:49:42 am »
SFML doesn't currently have a way to directly check if a TCP socket is connected or not. This might change in the future.

For now, you can check if a TCP socket is connected by comparing getRemoteAddress() against sf::IpAddress::None. If a TCP socket is connected it will always have a remote address and thus be unequal to sf::IpAddress::None.
if (socket.getRemoteAddress() != sf::IpAddress::None)
{
        // socket is connected
}
else
{
        // socket it not connected
}
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Multiple clients connecting to one server
« Reply #2 on: May 30, 2014, 09:56:41 am »
Quote
SFML doesn't currently have a way to directly check if a TCP socket is connected or not. This might change in the future.

For now, you can check if a TCP socket is connected by comparing getRemoteAddress() against sf::IpAddress::None.
So this is a direct way to check if it is connected, isn't it? :P
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Multiple clients connecting to one server
« Reply #3 on: May 30, 2014, 10:22:39 am »
So isConnected() would be... more direct than direct? :P
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

select_this

  • Full Member
  • ***
  • Posts: 130
  • Current mood: just ate a pinecone
    • View Profile
    • darrenferrie.com
Re: Multiple clients connecting to one server
« Reply #4 on: May 30, 2014, 10:25:50 am »
I agree that it's a little obtuse as it stands (getRemoteAddress could, for instance, point to what it is set to connect to, as opposed to what it is actually connected to - making an assumption that the user in question hasn't read the documentation first, which appears to be fairly common). An isConnected method would be good, even if it does nothing more complicated than that particular check in the first instance.
« Last Edit: May 30, 2014, 10:39:43 am by select_this »
Follow me on Twitter, why don'tcha? @select_this

Ninjaboi

  • Newbie
  • *
  • Posts: 13
    • View Profile
    • http://www.ninjasoftcorp.webs.com/index.html
Re: Multiple clients connecting to one server
« Reply #5 on: May 30, 2014, 06:51:55 pm »
Quote
SFML doesn't currently have a way to directly check if a TCP socket is connected or not. This might change in the future.

For now, you can check if a TCP socket is connected by comparing getRemoteAddress() against sf::IpAddress::None. If a TCP socket is connected it will always have a remote address and thus be unequal to sf::IpAddress::None.

Thank you, I wasn't aware getRemoteAddress() got and returned the address directly from the other machine on the connection and not from a stored sf::IpAddress when the sf::Socket was properly declared and used to connect with the client. Since it does basically check whether the other machine is still connected then it definitely serves the purpose I was wanting. Oh and I checked the documentation ( specifically the compiled HTML documentation provided in SFML's 2.1 download ) and this is what it read for getRemoteAddress():

Quote
Get the address of the connected peer.

It the socket is not connected, this function returns sf::IpAddress::None.


So I probably should have looked at that before instantly assuming all that function performed was a quick return of a stored IP address locally when the sf::Socket was binded to the peer. That was my "am I missing something here?" in this situation so now it's all cleared up  :D. By the way it seems there's a spelling error in that documentation as seen above. ( Wait I'm correcting spelling/grammar on the Internet?! Nobody does that!  ;) . )

Quote
So this is a direct way to check if it is connected, isn't it?
Quote
So isConnected() would be... more direct than direct?

A isConnected() member function for sf::Socket would be a pretty direct way to do it so I'm all for it. For my particular case I don't plan on changing this in SFML's source and compiling for myself. So I'll just stick with creating a function that takes an sf::Socket as an argument and let it return a bool value on whether or not it's connected.

Quote
I agree that it's a little obtuse as it stands (getRemoteAddress could, for instance, point to what it is set to connect to, as opposed to what it is actually connected to - making an assumption that the user in question hasn't read the documentation first, which appears to be fairly common). An isConnected method would be good, even if it does nothing more complicated than that particular check in the first instance.

Yeah that's what I figured it performed at first as seeing it in action in the sample code I figured that's exactly what it did. I really should have just checked the documentation for getRemoteAddress() in the first place and I most likely would have never needed to post this. I usually use the sample code and documentation as a way to learn what I need as it's the most direct way for me to understand the library. Tutorials are just added verbiage to me that I only rely on after I unsuccessfully couldn't figure out what I needed from the samples and documentation.


Maybe this should be presented in future tutorial revisions by providing a code example like binary did to check whether a peer is connected to a socket. Either way the forum yet again has an awesome help section so I appreciate the swift and resolving replies.

Happy coding!


EDIT:

Quote
A isConnected() member function for sf::Socket would be a pretty direct way to do it so I'm all for it. For my particular case I don't plan on changing this in SFML's source and compiling for myself. So I'll just stick with creating a function that takes an sf::Socket as an argument and let it return a bool value on whether or not it's connected.

Meant to say sf::TcpSocket, my bad  :P.
« Last Edit: May 30, 2014, 08:27:29 pm by Ninjaboi »