SFML community forums

Help => Network => Topic started by: Mars_999 on March 31, 2012, 05:53:35 pm

Title: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on March 31, 2012, 05:53:35 pm
I am about ready to jump off a cliff... I am having a hell of a time getting a server/client chat log going in my main menu using SFML and threads...

This is TCP, but right now could care less what it uses as long as it works...

So I started looking around and see libs like ClanLIb and such  have networking, but I would rather use SFML. So I though has anyone coded up a nice networking lib for chatting and sending game data using SFML as the only lib needed?

Thanks!
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Groogy on April 01, 2012, 02:53:58 am
The whole socket interface will still be the same. And you can mix the usage of TCP and UDP depending on the importance of the package.

I don't think changing library will help you much if you are having problem grasping the concept. I haven't used SFML for this myself but I have made a chat client using sockets and TCP yes. Though I have no idea why you are having problem or what you are getting stuck on.

Should we start simple? From the start? Are you capable of doing a manual handshake? Have a client sending a connect message to a server at intervals until the server responds? If you can, then try and extend this so it can handle several clients at the same time.

This is probably the key to get it to work for you, small steps, one at a time. Otherwise you will just trip and fall ;)
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Walker on April 01, 2012, 03:23:29 am
There are networking libraries around. Some are relatively simple socket wrappers (like SFML) and some have higher-level features like client/server stuff.

I tried some game networking libs when I first wanted to make networked games and it didn't help at all. I have had far more success using raw sockets then writing a wrapper over it to support extra stuff I wanted like compression.

Bottom line:
I don't think changing library will help you much if you are having problem grasping the concept.

If you post your actual problem in the networking part of the forum, people will definitely help you out. But a few tips: Use the console. Don't use threads.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 01, 2012, 03:43:42 am
Thanks guys for the help....

AFAIK I need to use threads... The whole app stalls when I run the server client stuff and not what I want to happen for obvious reason.

I can connect to each other stuff like that but I need it threaded unless you a simple example where their is no stalling while waiting for client to send or receive ect.. and same for server. When I use the simple example and drop it into my GUI chat interface due to blocking the user can't go back or do anything... This is the issue and then with threading I need to use mutexes correct for the data I am sharing to update...

e.g. a string for the chat log that gets received will need to be locked/unlocked

Thanks!
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Groogy on April 01, 2012, 04:04:44 am
Yes you need to use threads in order to have asynchronous sockets.

But you aren't giving us much information. But I will still stand with the advice that you should take small baby steps forward. So if you revert back to only having a threaded handshake/connection and disconnection working. Make sure it works and then we can take it from there to see where your problem is.

You have to understand that with networking is that a thousand things can go wrong without it even giving an effect until later. And so on and so on. That's why I recommend taking small steps to ensure that what you have done right now works as intended.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Tank on April 01, 2012, 01:14:38 pm
Yes you need to use threads in order to have asynchronous sockets.
That's not quite true. Sockets can be set to non-blocking and especially that makes sense in games where you have a loop running all the time.

The question one always has to ask himself: Is a thread *really* needed? If you can go with polling then do it, it saves a lot of time and trouble and in the end you don't benefit from threading as you're entering critical sections anyways mostly all the time.

That's different when your application's main thread is blocking, e.g. if you have a console application waiting for user input or even a GUI application that's blocking on events.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Groogy on April 01, 2012, 03:47:00 pm
If sockets are set to be asynchronous/non-blocking then the socket API provides the thread and queuing construct for you. There's always a thread ;) The difference is if you are doing it yourself or if the API is doing it. There's some pro's for doing it yourself as the queuing can be done in several ways and most often is decided on how your application looks.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Laurent on April 01, 2012, 04:07:01 pm
Quote
If sockets are set to be asynchronous/non-blocking then the socket API provides the thread and queuing construct for you. There's always a thread
I don't think that there are threads involved when you use non-blocking sockets.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 01, 2012, 05:49:27 pm
Tank or anyone else... I don't see anything in SFML for using a polling system. And I think my issue is all having to do with threading as its nightmare to keep straight! :(
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Tank on April 01, 2012, 05:53:59 pm
@Groogy:
That's again not true. ;) Sockets are simple streaming file I/O and have nothing to do with threads themselves. The difference between blocking and non-blocking sockets is how the operating system (or better speaking of the kernel) notifies the application of events. When blocking, it waits for a proper interrupt before giving back control, when non-blocking the current state is polled and control is given back to the caller immediately.

So when you run a loop at a high frequency (like being done in games) there's often no need use a separate thread for socket I/O.

@Mars_999:
sf::Socket::setBlocking (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Socket.php#a165fc1423e281ea2714c70303d3a9782)
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 01, 2012, 06:14:23 pm
So if I set the socket to non blocking I can basically put

if(socket->receive(packet) != sf::Socket::Done)

in the event loop like any other event? e.g. Draw() or Upate() for say game objects?

while(true)//game loop
{
GetPackets();//if(socket->receive(packet) != sf::Socket::Done) is in here...
PhysicsUpdate();
LogicUpdate();
Draw();
TimerUpdate();
}

Hope you are following me, in saying I can just treat the receive() as if it were a polled event in a switch() for sf::Events....
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Tank on April 01, 2012, 07:11:15 pm
Yup.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 07, 2012, 06:24:54 pm
Sigh, this is what I have so far and works, but the issue is I can't get the Client() to allow messages from the Server to be updated each time one is sent... It's like they are blocked....

Code: [Select]
#include "stdafx.h"

const unsigned short PORT = 5000;
const std::string IPADDRESS("127.0.0.1");

bool quit = false;
std::ofstream fout("test.txt");

template<class T>
class SharedType
{
public:
std::vector<T> data;
sf::Mutex mutex;

SharedType(){}
~SharedType(){}
void Push(const T& t)
{
mutex.lock();
data.push_back(t);
mutex.unlock();
}
T Get(void)
{
T t;
mutex.lock();
if(!data.empty())
t = data.back();
mutex.unlock();
return t;
}
void Pull(std::vector<T>& v)
{
mutex.lock();
v = data;
data.clear();
mutex.unlock();
}
void Clear(void)
{
mutex.lock();
data.clear();
mutex.unlock();
}
};
SharedType<std::string> data;

void Server(void)
{
std::list<sf::TcpSocket*> clients;
sf::SocketSelector selector;
sf::TcpListener listener;

listener.listen(PORT);
selector.add(listener);

while(!quit)
{
if(selector.wait(sf::seconds(2.0f)))
{
if(selector.isReady(listener))
{
sf::TcpSocket* client = new sf::TcpSocket;
if(listener.accept(*client) == sf::Socket::Done)
{
clients.push_back(client);
selector.add(*client);
            }
        }
else
{
//receive messages from clients
for(std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
{
sf::TcpSocket& client = **it;
if(selector.isReady(client))
{
sf::Packet packet;
std::string clientMsg;
                    if(client.receive(packet) == sf::Socket::Done)
{
packet >> clientMsg;
std::cout << "\nClient said: " << clientMsg << std::endl;
clientMsg.clear();
}
}
}
}
}
//send messages?
for(std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
{
sf::TcpSocket& client = **it;
if(selector.isReady(client))
{
sf::Packet packet;
std::string s;
s = data.Get();
data.Clear();
if(!s.empty())
{
packet << s;
if(client.send(packet) == sf::Socket::Done)
{
std::cout << "\nMessage sent to client: " << s << std::endl;
}
}
}
}
}
for(std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
{
if(*it)
delete *it;
}
}
void Client(void)
{
std::string s;
sf::Packet packet;
sf::TcpSocket socket;
socket.setBlocking(false);
while(true)
{
if(quit)
break;
socket.connect(IPADDRESS, PORT);
if(socket.getRemotePort())
break;
}
while(!quit)
{
if(socket.receive(packet) == sf::Socket::Done)
{
packet >> s;
std::cout << "\nThe server said: " << s << std::endl;
}
packet.clear();
s.clear();

s = data.Get();
data.Clear();
if(!s.empty())
{
packet << s;
if(socket.send(packet) == sf::Socket::Done)
{
std::cout << "\nMessage sent to server: " << s << std::endl;
}
}
packet.clear();
s.clear();
}
}
void GetInput(void)
{
std::string s;
std::cout << "\nEnter \"exit\" to quit or message to send: ";
std::cin >> s;
data.Push(s);
if(s == "exit")
quit = true;
}
int main(int argc, char* argv[])
{
sf::Thread* thread = 0;

char who;
    std::cout << "Do you want to be a server (s) or a client (c) ? ";
    std::cin  >> who;

    if(who == 's')
thread = new sf::Thread(&Server);
else
thread = new sf::Thread(&Client);

thread->launch();

while(!quit)
{
GetInput();
}
if(thread)
{
thread->wait();
delete thread;
}

std::vector<std::string> temp;
data.Pull(temp);
for(unsigned int i = 0; i < temp.size(); ++i)
fout << temp[i] << std::endl;

return 0;
}
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 08, 2012, 01:05:37 am
Anyone wants to, the code posted above is complete and should be drop and compile to test for yourself... after you update the IP to whatever you need....

I am not sure if this is a bug or what...
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 08, 2012, 06:13:54 am
Anyone?????
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 08, 2012, 08:46:19 am
Sigh..... this has to be a bug....

I am getting not ready when I try to receive anything when I test the returned status on non-blocking sockets....

This is SFML2.0 and MSVC++ 2010...

switch(socket.receive(packetReceive))
      {
         case sf::Socket::Done:
            std::cout <<  "done\n";
            break;
         case sf::Socket::Disconnected:
            std::cout << "disconnected\n";
            break;
         case sf::Socket::Error:
            std::cout << "error\n";
            break;
         case sf::Socket::NotReady:
            std::cout << "not ready\n";
            break;
      }
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on April 08, 2012, 08:54:34 pm
Can someone please post his code as a sticky for others to see? This code works for a very very simple client/server chat back and forth example I came up with, to show others after beating my head against the wall, I figured I would show others to help them with their first examples....

Code: [Select]
#include "stdafx.h"

const unsigned short PORT = 5000;
const std::string IPADDRESS("192.168.0.100");//change to suit your needs

std::string msgSend;

sf::TcpSocket socket;
sf::Mutex globalMutex;
bool quit = false;

void DoStuff(void)
{
static std::string oldMsg;
while(!quit)
{
sf::Packet packetSend;
globalMutex.lock();
packetSend << msgSend;
globalMutex.unlock();

socket.send(packetSend);

std::string msg;
sf::Packet packetReceive;

socket.receive(packetReceive);
if(packetReceive >> msg)
{
if(oldMsg != msg)
if(!msg.empty())
{
std::cout << msg << std::endl;
oldMsg = msg;
}
}
}
}
void Server(void)
{
sf::TcpListener listener;
listener.listen(PORT);
listener.accept(socket);
std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
}
bool Client(void)
{
if(socket.connect(IPADDRESS, PORT) == sf::Socket::Done)
{
std::cout << "Connected\n";
return true;
}
return false;
}
void GetInput(void)
{
std::string s;
std::cout << "\nEnter \"exit\" to quit or message to send: ";
std::cin >> s;
if(s == "exit")
quit = true;
globalMutex.lock();
msgSend = s;
globalMutex.unlock();
}
int main(int argc, char* argv[])
{
sf::Thread* thread = 0;

char who;
    std::cout << "Do you want to be a server (s) or a client (c) ? ";
    std::cin  >> who;

    if(who == 's')
Server();
else
Client();

thread = new sf::Thread(&DoStuff);
thread->launch();

while(!quit)
{
GetInput();
}
if(thread)
{
thread->wait();
delete thread;
}
return 0;
}
Title: Re: Anyone here have a project made using SFML for networking?
Post by: GatorQue on July 04, 2012, 06:35:39 am
Mars,

I have been reviewing your code and hope that this reply will help you out. In my reading and experience working with networking code there are basically two techniques to implement the code.
- Client/Server
- Peer-To-Peer

In the first model you create a server who has one thread dedicated to "accepting" new client connections. These connections all come in on the "listening" port, but typically, the client provides some random port (ephemeral). Once accepted, the server will typically spawn a "client thread" to handle communicating to the client.  The client code is usually pretty simple, a single "connect" call to the server IP address and port and then uses that "socket" to send and receive data from the server.
Another way to implement a client/server model is to have the server poll the incoming "socket" for client activity. If activity is found, then it processes the activity quickly and then returns to polling again. To do this, you must enable "non-blocking" sockets on the listening socket you create for the server.  The client code is the same as in the previous implementation, but you can also cause the client to poll for incoming data from the server in a non-blocking way by enabling "non-blocking" sockets for the client too.

In the Peer-To-Peer model you create multiple socket connections to all of your "peer" friends, there is no centralized server from which everyone tries to communicate.  Another way to implement the Peer-To-Peer model is to use "broadcast" packets which get blasted out to anyone on the _same_ network (in other words, this is what many LAN games use, but doesn't work over the internet). This model is less centralized.

Now, getting back to your code.  In your Server() method you "listen" and "accept" a connection, and your socket will block until you "accept" your first client.  At which point it will exit and run the "DoStuff" in a separate thread.  The problem is that you stop "accepting" any new clients. Therefore you can only have 1 client and 1 server at a time. It would be better if you made the "server" method into a thread and while loop so it could "accept" as many clients as you wanted.  Each client that was "accepted" would spawn another thread to process sending data to that client.

Thread 1: Run while loop as server to listen and accept client connections
Thread 2: Run while loop accepting local input from the keyboard and posting this input to the client threads below.
Thread 3..n: Run while loop receiving data from the socket provided by the Accept call. This is the thread that will be spawned by Thread 1 above. Monitor a shared "broadcast" string to be sent to the client when Thread 2 posts to this shared "broadcast" string.  Print any "string" messages received from the client socket to which this thread is responsible for.

I hope these explanations help, please write back soon with additional questions.
Title: Re: Anyone here have a project made using SFML for networking?
Post by: Mars_999 on July 04, 2012, 09:12:52 am
Thanks for the info! I will take a look at it more later on.