Once with a colleague, we faced the problem of real-time multiplayer implementation on CoronaSDK. At first, we tried the pubnub.com service, but over time they realized that they were not satisfied with their latency (they have everything via http) and prices. Not finding anything better, we decided to quickly create our bike on Node.js (or rather a scooter, because the entire server code fits in 90 lines with comments).
Named as a joke NoobHub. Distributed under the license WTFPL.
The thing turned out to be quite fast and, judging by the feedback from users, able to spin for months on the server without restarting and memory leaks. System requirements: Node.js 0.6.x and higher (included in the standard Ubuntu package), no additional modules are required.
If you are writing a mobile multiplayer application on Lua using CoronaSDK, Moai or Gideros, then there is good news: the client for these SDKs work fine, take it and use it.
')
Some facts:
- Several dozens of applications from different developers have been released, everyone is praised (there is nothing to mess). Here, for example, a frequent guest of Russian tops, Durak HD
- Write your client for any language where there are sockets - easier than ever
- Lua code can serve as an example of working with LuaSocket
- My test server is in a demo project, so I don’t even need to raise anything to test (the number of testers periodically rises to 200 CCU. I hope no one mistakenly uses it in production, on that server just 64 Mb RAM ...)
Using
Started the server:
$ node server.js
On the client created an object:
hub = noobhub.new({ server = "127.0.0.1"; port = 1337; });
Subscribed to the channel, in the callback function we process the message of other participants:
hub:subscribe({ channel = "hello-world"; callback = function(message) if(message.action == "ping") then print("Pong!") end; end; });
Sent a message:
hub:publish({ message = { action = "ping", timestamp = system.getTimer() } });
Boring details
The key element of the Node.js script is the
server object, which listens to the port and responds to connections. For each of them, a
socket is created with a unique hash for later searching and deleting, if necessary.
Sockets in turn listen for data retrieval and close events.
They recognize two types of messages: __SUBSCRIBE____ENDSUBSCRIBE__ - subscription to the channel,
__JSON__START _ <_ MESSAGE> __ JSON__END__ is an arbitrary message. When subscribing, a socket is added to the
CHANNELNAME pool and all subsequent messages coming through this channel will be transmitted to the newcomer. In the second case, the body
MESSAGE will be addressed to all subscribers of the channel
CHANNELNAME . To disconnect, it is enough to close the socket on the client side, and then the server knows what to do with the deserter.
It turns out that one EventLoop node does all the work of getting data and packaging it to clients in sockets. If there are many customers, a correspondingly increased cycle will delay the delivery of messages. The question is, of course, how many clients are needed for the drawdown to be at least somewhat noticeable. At 2k CCU, there was no drawdown of latency (we simply didn’t have more), but I doubt that 20k will give a noticeable drawdown.
On the client, everything is exactly the opposite, the client connects to the socket server, subscribes to the channel, and asynchronously listens to messages from other channel participants.
There is automatic reconnect & resubscribe when it is broken (it makes life easier for users with a bad connection on EDGE / 3G).
Total: simple Publish-Subscribe for small and even medium-sized projects.
Source code of the server and clients:
https://github.com/Overtorment/NoobHub