bzar
A Commando
Back story
While coding wars I've stumbled upon many problems with creating rich multiplayer web-based games. Some of them exist because the communication supported by browsers is not really game-friendly. The HTTP protocol is inherently stateless, so some overhead is required to keep sessions using cookies and whatnot. Each communication requires a new connection, raising lag. Servers cannot push data to clients, because the system was designed for request-based applications, like web pages mostly are.
The ones more experienced with web programming are now thinking: "you can get around all that using long polling/comet/whatever!". Yes, but most web servers are not really up to the task of serving a huge amount of long-polling clients. Most assume only a handful of concurrent connections with short lifespans. They are not suitable for long-lived connections. In addition, long polling techniques have their own set of disadvantages, such as missing data when reconnecting and http overhead and difficulties in communication between clients.
Now I imagine some of you think "Well, I can use a publish-subscribe messaging server such as Orbited for the data pushing!", but those bring a whole bunch of other problems, like separate logins for the web content and game data server. This is how we currently do things in Wars, and I got to thinking that there must be a nicer way.
Enter WebSockets. A nice, clean socket connection to a backend server. Although it's currently having some security issues, it is in my opinion the future of any two-way communication in web applications. This got me thinking: what if ALL dynamic data for an application was available only through a websocket server, and all html/css/js was served as static files. This means no server-side generation of HTML, only static files and a websocket to fill the page with data. A nice clean separation between the view and the model.
This model also solves the login issue, because one only needs to log into the web socket interface. The static pages are only templates, so getting them won't gain you anything. After tinkering with this idea for a while I noticed that if the login happens through a websocket, I of course cannot switch pages without losing my session. First I thought about creating a small view framework to keep the user actually on the same page and only dynamically modify the DOM to show different views. This idea was short-lived, because I wanted direct support for nice URL based navigation and back button and so on. So back to the drawing board. Next I thought about the current common implementation using cookies to send a session ID with each request. I didn't want cookies to have anything to do with my framework, but that reminded me of an interesting HTML5 feature: WebStorage or more accurately the SessionStorage part of it. This allowed me to store the session ID to the browser after successful login, and use it to restore my session after loading each page.
Now I had something I could use.
What have I done?
It's still a bit raw, but it already works. GameNode is a web application framework based on HTML5, websockets, node.js and node-websocket-server that provides a nice base for making both the server and client part of a web game (or application). The framework supports two main ways of communication: RMI (Remote Method Invocation) and messaging.
The RMI works by creating a "skeleton" object on the server, which is instantiated for each client. The client can then call the skeleton object's methods from the browser using an automatically generated stub object. The return values are automatically conveyed to a designated callback function. This is a nice way of handling stuff usually done with AJAX calls, or sending player actions (set game piece to these oordinates etc).
For a more speedy and two-way communication, we have messages. Both the server and client can implement message handlers, which process incoming messages. This is best for spontaneous client updates (an arrived chat message, locations of other players) and fast update messages for the server (location of player etc).
These things are in my experience best shown with examples. I have a few basic examples in the version control, which you can check out. The "test" example shows a very simple RMI/messaging test application, "chat" a basic chat server with dynamically creatable chat rooms (or "channels") and "auth" is a work-in-progress example of using the framework for login and sessions.
If you want to try any of the examples, you need node.js and a websocket-enabled browser such as chromium (or firefox 4 beta with the secret websocket switch set). Start the server (eg. "node testServer.js), and open the client html with your browser. Some examples require your browser to also support console logging, so be sure you have that (try typing "console.log" to your browser's javascript console).
If anyone's interested, give me a shout!
PS: I'm inclined to rewrite Wars using this thing when websockets get more common, so I'm writing this framework with mostly games in mind, although I'm sure it's good for so much more.
EDIT: typo
While coding wars I've stumbled upon many problems with creating rich multiplayer web-based games. Some of them exist because the communication supported by browsers is not really game-friendly. The HTTP protocol is inherently stateless, so some overhead is required to keep sessions using cookies and whatnot. Each communication requires a new connection, raising lag. Servers cannot push data to clients, because the system was designed for request-based applications, like web pages mostly are.
The ones more experienced with web programming are now thinking: "you can get around all that using long polling/comet/whatever!". Yes, but most web servers are not really up to the task of serving a huge amount of long-polling clients. Most assume only a handful of concurrent connections with short lifespans. They are not suitable for long-lived connections. In addition, long polling techniques have their own set of disadvantages, such as missing data when reconnecting and http overhead and difficulties in communication between clients.
Now I imagine some of you think "Well, I can use a publish-subscribe messaging server such as Orbited for the data pushing!", but those bring a whole bunch of other problems, like separate logins for the web content and game data server. This is how we currently do things in Wars, and I got to thinking that there must be a nicer way.
Enter WebSockets. A nice, clean socket connection to a backend server. Although it's currently having some security issues, it is in my opinion the future of any two-way communication in web applications. This got me thinking: what if ALL dynamic data for an application was available only through a websocket server, and all html/css/js was served as static files. This means no server-side generation of HTML, only static files and a websocket to fill the page with data. A nice clean separation between the view and the model.
This model also solves the login issue, because one only needs to log into the web socket interface. The static pages are only templates, so getting them won't gain you anything. After tinkering with this idea for a while I noticed that if the login happens through a websocket, I of course cannot switch pages without losing my session. First I thought about creating a small view framework to keep the user actually on the same page and only dynamically modify the DOM to show different views. This idea was short-lived, because I wanted direct support for nice URL based navigation and back button and so on. So back to the drawing board. Next I thought about the current common implementation using cookies to send a session ID with each request. I didn't want cookies to have anything to do with my framework, but that reminded me of an interesting HTML5 feature: WebStorage or more accurately the SessionStorage part of it. This allowed me to store the session ID to the browser after successful login, and use it to restore my session after loading each page.
Now I had something I could use.
What have I done?
It's still a bit raw, but it already works. GameNode is a web application framework based on HTML5, websockets, node.js and node-websocket-server that provides a nice base for making both the server and client part of a web game (or application). The framework supports two main ways of communication: RMI (Remote Method Invocation) and messaging.
The RMI works by creating a "skeleton" object on the server, which is instantiated for each client. The client can then call the skeleton object's methods from the browser using an automatically generated stub object. The return values are automatically conveyed to a designated callback function. This is a nice way of handling stuff usually done with AJAX calls, or sending player actions (set game piece to these oordinates etc).
For a more speedy and two-way communication, we have messages. Both the server and client can implement message handlers, which process incoming messages. This is best for spontaneous client updates (an arrived chat message, locations of other players) and fast update messages for the server (location of player etc).
These things are in my experience best shown with examples. I have a few basic examples in the version control, which you can check out. The "test" example shows a very simple RMI/messaging test application, "chat" a basic chat server with dynamically creatable chat rooms (or "channels") and "auth" is a work-in-progress example of using the framework for login and sessions.
If you want to try any of the examples, you need node.js and a websocket-enabled browser such as chromium (or firefox 4 beta with the secret websocket switch set). Start the server (eg. "node testServer.js), and open the client html with your browser. Some examples require your browser to also support console logging, so be sure you have that (try typing "console.log" to your browser's javascript console).
If anyone's interested, give me a shout!
PS: I'm inclined to rewrite Wars using this thing when websockets get more common, so I'm writing this framework with mostly games in mind, although I'm sure it's good for so much more.
EDIT: typo
Last edited by a moderator: