Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rnet] Simple and easy-to-use network module for raylib #753

Closed
raysan5 opened this issue Feb 13, 2019 · 40 comments
Closed

[rnet] Simple and easy-to-use network module for raylib #753

raysan5 opened this issue Feb 13, 2019 · 40 comments
Labels
new feature This is an addition to the library

Comments

@raysan5
Copy link
Owner

raysan5 commented Feb 13, 2019

As already mentioned several times by raylib community, a network module is a missing piece on raylib. Long ago I started drafting a possible network module API for raylib but due to lack of resources, project was stopped... I start this issue to list project specifications and references.

rnet is a simple and easy-to-use network library. Some desired features:

  • Available as raylib module (rnet.c) but also usable as a standalone library
  • No external dependencies (only the standard system libraries - winsock2.h/socket.h)
  • Self-contained in a single file (header-only) or two portable files: rnet.h + rnet.c
  • Focused on UDP protocol (probably the most useful for games)
  • Support WEB (WebSockets) and ANDROID platforms (if possible)

Just as a quick reference, the following APIs have been analyzed:

I'm not an expert on network programming, actually last time I remember doing some sockets code was on University... but here it is basic raynet API proposal (probably very improvable):

void InitNetworkDevice(NetworkConfig config);
void CloseNetworkDevice();
int NetworkConnect(int hostId, const char *address, int port);
void NetworkDisconnect(int hostId, int connectionId);
void NetworkSend(int hostId, int connectionId, int channelId, void *data, int length);
int NetworkReceive(int hostId, int connectionId, int channelId, void *data, int length);
// Maybe hostId, connectionId and channelId can be a `struct NetworkSocket`.

Just keep in mind this API is a very rough proposal...

EDIT: Added to list desired support for WEB and ANDROID.

@a3f
Copy link
Contributor

a3f commented Feb 13, 2019

NetworkDisconnect and NetworkSend could both fail, they should return an error code or give the user some way to find out what went wrong (e.g. Network is down or a timeout occurred). Speaking of timeout, how will NetworkReceive work?

Blocking till a packet arrives doesn't sound too useful, so I assume it will poll for new packets and return immediately?

@OvermindDL1
Copy link

Probably shouldn't use something so low level as raw tcp/udp style interfaces. Should probably build raynet around something like https://github.com/SLikeSoft/SLikeNet or so instead as they have actually useful constructs for games.

@Gamerfiend
Copy link
Contributor

Gamerfiend commented Feb 13, 2019

I think a NetworkSocket and NetworkData structs would be a good way to do it, with the latter having a void * ptr that the user can set as their data.

@Skabunkel
Copy link

Skabunkel commented Feb 13, 2019

One haircut later.
i have some input.
Aswell as questions

// This call can fail on windows, it is rare but should be accounted for.
bool InitNetworkDevice(NetworkConfig config); 

//Why is the hostid included here?
bool NetworkDisconnect(int hostId, int connectionId); 

//This should return something, maybe not int but atleast a bool. 
//But giving the user an option to track the sent bytes is useful
//Why is hostid included here?
//What is channelId supposed to be used for?
int NetworkSend(int hostId, int connectionId, int channelId, void *data, int length); 

//Why is hostid included here?
//What is channelId supposed to be used for?
int NetworkReceive(int hostId, int connectionId, int channelId, void *data, int length); 

Other than that i can only suggest expanding it with some encoding functions etc.

@Skabunkel
Copy link

I'll make this a separate thing, focusing on UDP and implementing WebSockets seems sort of weird?
I might have a different notion of what a WebSocket is in that case please explain.

Provided that the idea is to be able to make a GET and POST request this should not be impossible, however then we should sit down and focus on what part of the HTTP protocol, we would want since posts and gets can be very funcy if you let them.

@Skabunkel
Copy link

Probably shouldn't use something so low level as raw tcp/udp style interfaces. Should probably build raynet around something like https://github.com/SLikeSoft/SLikeNet or so instead as they have actually useful constructs for games.

  1. Raylib is written in c99 so this library could not be used if we want to keep it that way.
  2. See bullet point 2 in rays post.

@OvermindDL1
Copy link

  1. Raylib is written in c99 so this library could not be used if we want to keep it that way.

It itself is yes, hence why it should be entirely wrapped, it should not be exposed to the user of the library at all.

  • No external dependencies (only the standard system libraries - winsock2.h/socket.h)

It's license allows baking it into a project so it's no longer an external dependency.

@raysan5
Copy link
Owner Author

raysan5 commented Feb 13, 2019

Thanks to all of you for your answers! :)

@a3f @Skabunkel yes, functions should return some state info.
@a3f don't know yet how those functions should properly work.
@Gamerfiend agree.
@Skabunkel hostId is probably not required, I took it from Unity network API. Some basic encoding function could also be useful to encode/decode packages. About WebSockets, I understand is the equivalent of sockets to run on web, maybe I'm wrong with my assumption.
@OvermindDL1 Thanks for the sugestion but that's a big library, I prefer to keep it simple and self-contained.

@Skabunkel
Copy link

Skabunkel commented Feb 13, 2019

Ah, that makes sense. unsure how that would work in webasm but oh well, the joy of exploration.
Edit 1:
https://github.com/emscripten-core/emscripten/tree/incoming/tests/sockets
Edit 2:
Probably more this
https://github.com/emscripten-core/emscripten/blob/incoming/tests/websocket/websocket.c

@Skabunkel
Copy link

Skabunkel commented Feb 13, 2019

Android NDK sockets
https://github.com/wzbos/Android-NDK-Socket/tree/master/sample/app/src/main/jni/tcomm.c
This is just reference material, does not seem to scary based on it.
But i have to admit i do not read chinese so i might be wrong. 😄

@overdev overdev mentioned this issue Feb 16, 2019
17 tasks
@zakrent
Copy link

zakrent commented Feb 17, 2019

Why so low level? Some things like packet sequencing and relability would be nice (something like eg. ENet, look at packet flags), those things are hard to make for new programmers and would help them with networking.

@Syphonx
Copy link
Contributor

Syphonx commented Feb 18, 2019

@zaknet I've been working on small network module for raylib - hence why this issue was opened, I plan to have a similar api to sfml/sdl_net for those who want to use platform agnostic socket calls.

I've also got plans to include a, as you put it 'higher level' game api on top, the goal is to support basic replication, serialisation, callbacks, sequencing etc for those less familiar with networking

@Syphonx
Copy link
Contributor

Syphonx commented Feb 18, 2019

With raylib having quite a minimalist api however, my roadmap for the module is very much subject to change. Within the week I'll likely post a spec, outline what features I intend to add and we can have a discussion about what belongs in an api call, and what we can provide as examples :)

@raysan5
Copy link
Owner Author

raysan5 commented Feb 18, 2019

@Skabunkel Thank you very much for the links! I looks pretty good! Supporting WEB and ANDROID has been added to the list!
@zakrent I agree, intention is to offer a simple and easy-to-use API but I'd start with a bare-bones working solid version first.
@Syphonx I'm following your rnet implementation, you're doing a great work! I think you're using TCP at this moment, are you planning UDP support also? We can discuss it later on once specs published... Keep up the good work! :)

@raysan5
Copy link
Owner Author

raysan5 commented Feb 18, 2019

By the way, @Syphonx, do you think we could have a functional version to be included on raylib 2.5 in the following two months or so?

@Syphonx
Copy link
Contributor

Syphonx commented Feb 18, 2019

I plan to have barebones support for TCP/UDP, a low(er)-level socket api, serialisation helpers and some examples done in the next week or so @raysan5

@Syphonx
Copy link
Contributor

Syphonx commented Feb 18, 2019

Features like replication, data packet tags and more advanced features will likely be added on an 'as we go' basis

@raysan5 raysan5 added this to the raylib 2.5 milestone Feb 18, 2019
@raysan5 raysan5 pinned this issue Feb 19, 2019
@raysan5 raysan5 unpinned this issue Feb 19, 2019
@raysan5 raysan5 changed the title [raynet] Simple and easy-to-use network module for raylib [rnet] Simple and easy-to-use network module for raylib Apr 5, 2019
@raysan5 raysan5 removed this from the raylib 2.5 milestone Apr 23, 2019
@nxrighthere
Copy link

nxrighthere commented May 16, 2019

An attempt to use any networking library that includes winsock2.h on Windows, will result in name colliding and conflicts with Raylib functions and structures at the compilation, specifically: Rectangle, UnhideWindow, CloseWindow, and ShowCursor.

Windows headers already have these declarations. I'm surprised that you don't follow an appropriate naming conventions with a vendor-specific prefix, this is quite trivial thing in C.

@nxrighthere
Copy link

nxrighthere commented May 26, 2019

I used Raylib in NetDynamics if you're interested. I've added Ray prefix to all functions and renamed Rectangle to Rectangle2D. Without these modifications, it's impossible to build a project on Windows with Raylib and included winsock2.h.

@raysan5
Copy link
Owner Author

raysan5 commented Jun 14, 2019

@nxrighthere Hey! Excuse me for this super-late response, I completely forget about this issue...

About windows.h inclusion (or related headers), symbol collisions could be mostly avoided like explained on #857, also embedding the inclusion into its own module.

Personally I don't like prefixes (when I started raylib I came from C# world) but I agree it's the best option in C to avoid that kind of collisions... maybe in a future update of raylib...

Congrats for the NetDynamics, very nice project! Great code organization and github project presentation. I like it!

@nxrighthere
Copy link

nxrighthere commented Jun 14, 2019

@raysan5 Thanks, I glad that you like it.

Personally I don't like prefixes (when I started raylib I came from C# world) but I agree it's the best option in C to avoid that kind of collisions... maybe in a future update of raylib...

Well, it's not a problem for me I've just made a small script that renames everything. But, for example, people to whom I suggested Raylib in my community encountered the same problem, and they were really unhappy with that, so I think it would be better to solve this out of the box with the traditional approach.

Thank you for your work anyway, it's a very helpful thing for fast prototyping.

@raysan5
Copy link
Owner Author

raysan5 commented Oct 19, 2019

Just for reference, I found swrap library, looks very interesting!

@nxrighthere
Copy link

Such stuff is just a very basic UDP API, for multiplayer games, you will need a networking library with a mature protocol that carries at least these features:

This is only the tip of the iceberg, consider something that provides such feature-set out of the box. Godot is using ENet which is used in many modern games today such as League of Legends for example (they are using cryptography for payload on top).

@raysan5 raysan5 mentioned this issue Jan 28, 2020
3 tasks
@lmnt-dev
Copy link

For inspiration:
https://github.com/networkprotocol/yojimbo

@raysan5 raysan5 added the new feature This is an addition to the library label Jul 5, 2020
@paezao
Copy link

paezao commented Aug 10, 2020

Hey guys! Is someone working on this?

@raysan5
Copy link
Owner Author

raysan5 commented Aug 10, 2020

Hi @paezao! Not really, I did some review a while ago but it's not functional at this moment...

My plan was simplifying the API and use UDP-only.

@masterneme
Copy link

Hey @raysan5, I asked you recently about enet. You told me that you're looking for single files with single headers.

But do you actually like enet? I mean, if someone took the source code and put it all together in a single organized file+header, would you use it or does enet lack features that you want?

@nxrighthere
Copy link

A single-header fork is available here. It's used in several games in production.

@raysan5
Copy link
Owner Author

raysan5 commented Oct 20, 2020

@nxrighthere Oh! Thank you very much for sharing!

@masterneme
Copy link

What a coincidence @nxrighthere , I recently starred your fork before posting here, I hope @raysan5 likes it. I want to use it for some Unity projects.

@raysan5
Copy link
Owner Author

raysan5 commented Dec 1, 2020

Another great alternative: enet single-header fork: https://github.com/zpl-c/enet

@bloodhaze13
Copy link

zpl-c/enet is the particular repo that I used in my multiplayer pong clone I wrote a couple of days ago. I have little to no background in C and managed to get it up and going fairly quickly which suggests it must be fairly easy to use.

Rough mapping of code snippets to proposed API below:

- InitNetworkDevice()/CloseNetworkDevice() -> Handled by ENet in GameServerConnect()
- NetworkConnect() -> GameServerConnect()
- NetworkDisconnect() -> GameServerDisconnect()
- NetworkSend() -> GameServerPublish()
- NetworkReceive() -> GameServerPoll()

So a thin wrapper over ENet within the same single file seems viable, so long as your happy with the ENet license and whatever maintenance goes along with it. The only other convenience function that would be nice is some sort of transport-layer compression and encryption which should be possible before crafting the ENet packet.

I started having a look at the existing rnet code and for a novice like me it looks like it would be a little easier to maintain/debug than ENet since it is much simpler. That said there would probably be more work in completing it than an ENet wrapper. Effort/maintenance/functionality tradeoff I guess.

@raysan5
Copy link
Owner Author

raysan5 commented Jan 21, 2021

@bloodhaze13 thanks for the info! Current rnet implementation was contributed by an user following a proposed API but development was stopped, I tried to pick it up but it required more time than expected, I'm not an expert on networking...

Lately I also keep an eye to another very promising library: https://github.com/nathhB/nbnet

@vb-mich
Copy link

vb-mich commented May 22, 2021

Hello,
for an old project of mine I used this "Tiny Websockets" library https://github.com/Theldus/wsServer
It's works pretty well and quite RayLib-style (just a couple of .c file, written in C99), the only thing is that it doesn't support encryption yet, even tho there's an easy workaround for that.
[edit]
Oh, I just noticed that @Theldus actually forked RayLib as well XD

@raysan5
Copy link
Owner Author

raysan5 commented Jul 28, 2021

This issue has been open for too long, many alternatives have been proposed here and actually rnet.h implementation is still there for anyone willing to review/improve it. I'm closing the issue.

@raysan5 raysan5 closed this as completed Jul 28, 2021
@vb-mich
Copy link

vb-mich commented Aug 26, 2021

Mongoose Embedded web server seems to be a complete embedded and self contained web server written in C and shipped in a sigle C file (+header)
https://cesanta.com/docs/#build-options

I drop here this reference to keep track of it.

@nathhB
Copy link

nathhB commented Aug 29, 2021

Hello.

I'm the author of nbnet. I discussed with Ray and started working on a potential rnet implementation (as a nbnet wrapper). You can follow the progress here for now. Take a look at rnet.h for a good overview of the API.

@raysan5 raysan5 reopened this Sep 1, 2021
@raysan5
Copy link
Owner Author

raysan5 commented Sep 1, 2021

@nathhB I'm reopening the issue for further discussion!

@nathhB
Copy link

nathhB commented Sep 2, 2021

@raysan5 I forked raylib: https://github.com/nathhB/raylib.

This is where I will update rnet so you can look there when you want to review it. I'm gonna leave it as-is until it has been reviewed as I think it lays a good fundation to build upon. There are two files: rnet.h and rnet.c.

@raysan5
Copy link
Owner Author

raysan5 commented Oct 5, 2021

After reviewing rnet implementation using nbnet I got to the conclusion that nbnet is so good that a rnet wrapper does not make much sense. I checked the code and almost all rnet functions just implement a direct call to some nbnet function, maybe adding some tracelog or small check.

Other libraries used on raylib like miniaudio are more complex and having a top layer simplifying usage makes sense but nbnet already seems very easy to use, even for beginners.

Still, some nbnet usage examples will be added to the official raylib/examples/network and nbnet will be the go-to option recommended for raylib users wanting to add network features to their games. :D

@raysan5 raysan5 closed this as completed Oct 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature This is an addition to the library
Projects
None yet
Development

No branches or pull requests