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

Author Topic: Handling Multiple TCP Connections  (Read 18060 times)

0 Members and 1 Guest are viewing this topic.

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« on: December 18, 2010, 11:51:27 pm »
Hey,

I have a problem handling multiple TCP connections on a C++ app that uses SFML library to send and read TCP messages.

Let's say I need to have 5 TCP connections to the server once (can be also 10K, just for example..). When client 1 sends a message, the server process it and then should send a message to clients 2-5, let's say in that case that he should send the same message.
How can I do that?

Thanks!

nulloid

  • Full Member
  • ***
  • Posts: 134
    • View Profile
Handling Multiple TCP Connections
« Reply #1 on: December 19, 2010, 05:43:49 am »
What is your problem exactly?

I write a server for a game for about a month now. Here is how I do:

I have a [Server], [ClientPool] and a [ClientThread] class. If someone joins to the server, it creates a ClientThread for it, and drops it in the ClientPool. Now, if a client sends a message, the appropriate ClientThread calls the right method of the server (let's call newMessage(string message, ClientId from)), which takes care of things must be done. E.g. sending that message to every other client. (Well, this is not exactly how I do, but just simplified it for you. I'm in the middle of a redesigning process, creating message objects, command objects, etc, etc. :))

Was this answer helpful? :)

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #2 on: December 19, 2010, 09:22:45 pm »
It's a server game. As I said, lot of clients needs to get connected.
When I need to do something like what I need, the user is always opens the first chat. But I heard that I can't connect multiple chats and keep them alive and also connect with each other (eg. send the data I got from client 1 to 2, 3, 4, 5), and I have to always close the chats, store the IP loged in into a DB (non-sql, of course..) and when I need to send a message to one of the clients I must start a new chat from the server to the client.

1. Is that correct? There isn't a way keeping alive lot of TCP chats the same time and connect between them?
2. If it is, I think I have a problem here. If the server needs to open the chat, then the client needs to listen to it always. But when the client connected to a wireless and there's a fiewwall, I can't connect him, can I? How do you solve that problem?

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #3 on: December 19, 2010, 10:16:13 pm »
Using the Socket Selector. It's a very useful tool for multiple connections.
http://www.sfml-dev.org/tutorials/1.6/network-selector.php

With the firewall, that's not problem with SFML. It's the firewall. The port you are using needs to be forwarded/allowed in the firewall settings.

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #4 on: December 19, 2010, 10:50:08 pm »
Oh, thanks! I didn't knew about network selector. But how can I do with that what I wanted in first place (my first message)?

Thanks!

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #5 on: December 19, 2010, 11:02:58 pm »
So you effectively want to broadcast the message to everyone but the sender (and of course the listener)?

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #6 on: December 19, 2010, 11:09:30 pm »
Yeah, because I can go on from there. It won't be like that in the game, but after I'll see a working code for broadcast the message to everyone but the sender, I'll know how to build what I want exactly. So yes :D

Thanks..!

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #7 on: December 19, 2010, 11:12:45 pm »
Right.
1. When a client connects, add their socket to a client array.
2. When a message comes in, loop through the client array sending the message to everyone except the person who sent it (test the socket of the client who sent the message against the array of clients to find out who to skip)

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #8 on: December 19, 2010, 11:16:39 pm »
That's it!! Client array! How can I do that? I'm pretty new in C++, sorry for that, but yeah :X
I never worked with C++ and the client isn't written in C++, but I found SFML to be the best network library so I'm using it.

Also in step 2, how can I access the sendes's IP? I mean, all I see here, in that selector is (in the SFML sample):
                sf::Packet Packet;
                if (Socket.Receive(Packet) == sf::Socket::Done)
                {
                    // Extract the message and display it
                    std::string Message;
                    Packet >> Message;
                    std::cout << "A client says : \"" << Message << "\"" << std::endl;
                }

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #9 on: December 19, 2010, 11:36:36 pm »
I don't see the need to access the sender's IP address when you recieve a message from them. You can sort of access their IP when they first connect:
Code: [Select]
       sf::IPAddress Address;
        sf::SocketTCP Client;
        Listener.Accept(Client, &Address);
        std::cout << "Client connected ! (" << Address << ")" << std::endl


For a dynamic array of Sockets (if you don't have a maximum allowable number of clients), look at using a vector:
Code: [Select]

#include vector
//other includes here

std::vector<sf::SocketTCP> Clients;


If you have a maximum number of clients:
Code: [Select]

sf::SocketTCP Clients[10];

Note that this example has a max of 10 clients - but you'll need to have checks in place. This only limits the size of the data structure.

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #10 on: December 19, 2010, 11:40:50 pm »
That's exactly the problem, I need to know from what IP I'm getting every message. How can I test which IP sent me the message and skep him when I don't know any message's sender IP?

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #11 on: December 19, 2010, 11:43:43 pm »
Instead of skipping the IP, skip the socket. It's a lot easier.
e.g. from the SFML site:
Code: [Select]

    if (Socket == Listener)
    {
        // If the listening socket is ready, it means that we can accept a new connection
        sf::IPAddress Address;
        sf::SocketTCP Client;
        Listener.Accept(Client, &Address);
        std::cout << "Client connected ! (" << Address << ")" << std::endl;

        // Add it to the selector
        Selector.Add(Client);
    }


Here, they test the actual listener socket. You'll probably need pointers and stuff, but it's the same idea. Some of it you'll have to work out yourself. :wink:

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #12 on: December 19, 2010, 11:45:50 pm »
Oh, now I get it...
Well, you really helped me! Thank you very much!

tntexplosivesltd

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Handling Multiple TCP Connections
« Reply #13 on: December 19, 2010, 11:46:17 pm »
Or, you could store an array of the IPs instead of the sockets. Then you can access the IP of the sender, and compare it to the array.

EiTkoCaT

  • Newbie
  • *
  • Posts: 47
    • View Profile
Handling Multiple TCP Connections
« Reply #14 on: December 21, 2010, 08:19:55 pm »
I don't undertand an important thing here.
Let's say I currently have 3 clients (could be 10K either..). Client A just connected to the server and send a log in request as a message with username and password. Now user B and C also connected and loged in. Surely they also got a OK message. Now, user B wants to change he's status from "Happy" to "Sad", so he sends a message to the server. So now I'm gonna need to send to clients A and C that client B's status changed. How can I send them a thing like that? How can I identify a client who is sending a message? The message that client B sends to the server should be, for example:
status sad
and then the server should send him back:
stats changed
and the server needs to send to user A and C:
user B status change sad

Just an example. So how can I do that? Thanks!