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

Author Topic: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11  (Read 9515 times)

0 Members and 1 Guest are viewing this topic.

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Hi guys,

I started focusing on SFML. So I plan to migrate my Game Engine Project (some kind of multiplayer, isometric hack'n'slay roleplaying) by using SFML. And this means to migrate my networking framework from SDL to SFML.

I made this during today - including deals with the questions "how to install SFML2.0 on my ubuntu 12.04 via suitable PPA" and "how does networking works with SFML 2.0". Now my framework looks even clearer and hopefully more stable.

What's that framework about: It is a TCP-based Server-Client-Framework, based on SFML 2.0 and C++11, as the title already said. You can find the code my GitHub repository https://github.com/cgloeckner/networking - feel free to use, share and fork it. It's open source!

To avoid writing a large article, I'd just like to point out some features. You can find even more information in the README-file at the repository.

  • Multithreaded Server-Client architecture
  • TCP-based communication
  • Multi-Plattform by modern C++11 and SFML features
  • Limit number of clients (or keep open-end)
  • Block / Unlock clients based on their IP-address
  • Grouping clients to logical partitions
  • Easy-to-use: it's header-only!
  • Flexible: Use your own protocol workflow

I hope you like it. Feel free to comment on this framework (praise, criticism, questions etc.)

Finally I'd like to say: SFML is great! Today's absolute highlight was getting to know about sf::Packet - it's f*cking godlike ;)

Kind regards
Glocke
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Canadadry

  • Hero Member
  • *****
  • Posts: 1081
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #1 on: June 20, 2013, 10:33:52 am »
Hi,

I've read the example you provided and it look just great.  :D I've always search for something that make writing a client/server communication simple but I've never found something really simple and useful. Now it's done thanks to you.

I hope some day Laurent will write more than just a socket class and more client/server object. Like he did with graphic renderer. Your project would clearly make the job.  :D

Just one question why in the BaseProtocol::send and received doesn't you directly provide the packet instead of the socket? In my opinion, we don't want  the user to mess with the socket here. We just want to let it him read/write data onto a packet. Don't you think ?

Again great job with this  :D

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #2 on: June 20, 2013, 10:42:29 am »
Quote
I hope some day Laurent will write more than just a socket class and more client/server object. Like he did with graphic renderer.
This is clearly something that I want to do. Rewriting the network module to provide a higher-level asynchronous API will most likely be the big task of SFML 3 ;)
Laurent Gomila - SFML developer

Canadadry

  • Hero Member
  • *****
  • Posts: 1081
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #3 on: June 20, 2013, 11:37:28 am »
I'm glad to here that.  :)
You won't be out of work for a long time with plan like that.  :P

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #4 on: June 21, 2013, 02:54:01 am »
I've read the example you provided and it look just great.  :D I've always search for something that make writing a client/server communication simple but I've never found something really simple and useful. Now it's done thanks to you.

Nice to hear that, thanks! :) I aim at simplicity - I guess this works ^^

Just one question why in the BaseProtocol::send and received doesn't you directly provide the packet instead of the socket? In my opinion, we don't want  the user to mess with the socket here. We just want to let it him read/write data onto a packet. Don't you think ?

Well, this API is currently "unstable" referring to it's signture :D It was just my first draft. But I agree: using the package class directly would be a greater win for more abstraction. I was thinking about abstracting the whole stuff even more, so you can use not only SFML sockets but also Boost asio oder SDL_net. For this case I plan to implement something like sf::Packet, based on each of the three socket APIs to make my framework even more flexible and not only too-focused on a specific framework (as it currently is by using SFML).

Of course this is the SFML-forum - so it's "expected" that it works with SFML - but not as the only possibility :)
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
SFNet - Simple and Fast Networking
« Reply #5 on: June 22, 2013, 10:00:12 am »
Currently I think about naming my project. It is called "Networking", yet. What do you think about the name "SFNet - Simple and Fast Networking"? In this case I would stay at SFML-Network as dependency in the first place, because the sf::Packet class is "so mighty", that I don't even want to implement it myself using SDL_net or Boost::Asio.

In addition to the rename, I plan to support UDP as well as Peer-to-Peer connections. So I have some additional questions to you:

  • How to solve the UDP-support? Afaik I cannot "easily" change the socket protocol and just "plug" an UDP-socket to the client/server instead of a TCP-socket. UDP does not "connect" in the sense of TCP. So there are not connect- or disconnect-methods. As well there is no TCP-listener socket. Also a UDP-socket should obtain/returns (as the UDP-socket implementation by SFML already does :) ) the target'ss/source's hostname and port number when sending/receiving. So I think of seperate client- and server-classes which are using UDP. They would be derived from a BaseServer/BaseClient (the TCP version would be derived as well). Any ideas?
  • Does Peer-to-peer connections make sense using TCP? In case of UDP it would be easiest: each peer knows each other peer's hostname and port and can send directly using its UDP socket. For TCP each peer needs an additional listener socket to accept new peers. Also broadcasting (e.g. when a new peer was added) would be a lot easier when using UDP compared to using TCP. So does it even make sense in this case? In my opinion, peer-to-peer makes only sense when using UDP - but I'm neither a "networking-God" nor very experienced in peer-to-peer architectures.

Kind regards
Glocke
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #6 on: June 22, 2013, 10:12:44 am »
Quote
In this case I would stay at SFML-Network as dependency in the first place, because the sf::Packet class is "so mighty", that I don't even want to implement it myself using SDL_net or Boost::Asio.
You don't need any networking function to implement a sf::Packet-like class. It's just a utility that serializes things: it transforms typed data to a sequence of raw bytes.
The only thing you need is the hton/ntoh set of functions, which convert primitive types to network byte order. But they can easily be emulated, if you don't want to depend on each OS networking header just for these functions.
Laurent Gomila - SFML developer

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #7 on: June 22, 2013, 10:21:29 am »
Quote
In this case I would stay at SFML-Network as dependency in the first place, because the sf::Packet class is "so mighty", that I don't even want to implement it myself using SDL_net or Boost::Asio.
You don't need any networking function to implement a sf::Packet-like class. It's just a utility that serializes things: it transforms typed data to a sequence of raw bytes.
The only thing you need is the hton/ntoh set of functions, which convert primitive types to network byte order. But they can easily be emulated, if you don't want to depend on each OS networking header just for these functions.

Thanks for that! Afaik SDL_net also provides some functions for this conversion. They also differentiate between 16- and 32-bit conversion for reading and writing purpose. When to use which? I didn't found an answer to this question, yet - so I should ask this question :D

All together is seems not too difficult to make "SFNet" support SFML-Network, SDL_net and Boost::Asio, I guess :D
« Last Edit: June 22, 2013, 10:27:39 am by Glocke »
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #8 on: June 22, 2013, 10:24:06 am »
Quote
They also differentiate between 16- and 32-bit conversion for reading and writing purpose. When to use which?
I'm not sure I understand your question, what do you mean?
Laurent Gomila - SFML developer

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #9 on: June 22, 2013, 10:29:31 am »
I was thinking about using std::basic_iostream for this purpose: It already has operator<< and operator>> for several types. So the actual socket implementation (I would write) should "only" obtain the data, apply the endianess conversion and send it through itself (the socket). That's it?

Quote
They also differentiate between 16- and 32-bit conversion for reading and writing purpose. When to use which?
I'm not sure I understand your question, what do you mean?

I mean there are e.g. htonl and htons which might convert "host to network long" and "host to network short" (referring to integer). Also SDL_net provides WriteNet16 / WriteNet32 (or with such names). They obviously provide 16-bit (short) and 32-bit (long) integers. But I don't know which to use. I guess there is not a "one fits all cases"-solution. That's why I'm asking :)
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #10 on: June 22, 2013, 10:34:18 am »
Quote
I was thinking about using std::basic_iostream for this purpose: It already has operator<< and operator>> for several types. So the actual socket implementation (I would write) should "only" obtain the data, apply the endianess conversion and send it through itself (the socket). That's it?
This is not the right strategy. std::basic_iostream will process data and send it to its attached std::streambuf, which you would have to override to get the data, using this approach. But it's already too late: the streambuf receives the data as byte blocks, you already lost the original types. You must operate at a higher-level, in fact you need to implement your own stream-like interface, with your own operators << and >>, because each type of data must be treated differently.

Quote
I mean there are e.g. htonl and htons which might convert "host to network long" and "host to network short" (referring to integer). Also SDL_net provides WriteNet16 / WriteNet32 (or with such names). They obviously provide 16-bit (short) and 32-bit (long) integers. But I don't know which to use. I guess there is not a "one fits all cases"-solution. That's why I'm asking
Use the 16 bits function to write 16 bits integers, and the 32 bits function to write 32 bits integers. Sorry for such an obvious answer, but that's really just it ;D

By the way, these functions only perform a byte swap, it's really straight-forward to implement directly. All you need is a reliable endianness detection (either at compile time or at runtime).
« Last Edit: June 22, 2013, 10:36:12 am by Laurent »
Laurent Gomila - SFML developer

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #11 on: June 22, 2013, 10:42:45 am »
Quote
I was thinking about using std::basic_iostream for this purpose: It already has operator<< and operator>> for several types. So the actual socket implementation (I would write) should "only" obtain the data, apply the endianess conversion and send it through itself (the socket). That's it?
This is not the right strategy. std::basic_iostream will process data and send it to its attached std::streambuf, which you would have to override to get the data, using this approach. But it's already too late: the streambuf receives the data as byte blocks, you already lost the original types. You must operate at a higher-level, in fact you need to implement your own stream-like interface, with your own operators << and >>, because each type of data must be treated differently.

Oops :D Ok, you are right: if I do it on my own, I'll know, who and that it works the way is want :D

Quote
I mean there are e.g. htonl and htons which might convert "host to network long" and "host to network short" (referring to integer). Also SDL_net provides WriteNet16 / WriteNet32 (or with such names). They obviously provide 16-bit (short) and 32-bit (long) integers. But I don't know which to use. I guess there is not a "one fits all cases"-solution. That's why I'm asking
Use the 16 bits function to write 16 bits integers, and the 32 bits function to write 32 bits integers. Sorry for such an obvious answer, but that's really just it ;D

By the way, these functions only perform a byte swap, it's really straight-forward to implement directly. All you need is a reliable endianness detection (either at compile time or at runtime).

Okay, seems logically :D

But what do you mean with "byte swap"? I thought this was the thing to do, because least vs. most significant bytes first. What to do else? (I guess the answer is as obvious as "always" :D )
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #12 on: June 22, 2013, 10:54:09 am »
Quote
But what do you mean with "byte swap"? I thought this was the thing to do, because least vs. most significant bytes first. What to do else? (I guess the answer is as obvious as "always"  )
You already answer in your question, I haven't got anything to add. You just need to convert all your primitive types to a known byte order, so on systems that don't match this order you need to swap the bytes of types which size is greater than one byte.
Laurent Gomila - SFML developer

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #13 on: June 22, 2013, 10:56:36 am »
You just need to convert all your primitive types to a known byte order, so on systems that don't match this order you need to swap the bytes of types which size is greater than one byte.

Just to make sure I understood correctly: I should decide a byte order for networking (e.g. big endian). Than I check (e.g. at compile time using some preprocessor stuff) which byte order is used by the system. It it's not big endian, I'll convert the data to big endian and send it. Else I send it directly. Same at receiving. That's right?
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TCP-Based Server-Client Framework - based on SFML 2.0 and C++11
« Reply #14 on: June 22, 2013, 11:03:06 am »
You understood perfectly ;)
Laurent Gomila - SFML developer