network engine written in Python programming language licensed under ... more than 1800 unit tests. It is very ... server with text protocol using JSON format. JSON is an ... needed to write the good tests, test automation, sharing of setup and ...
1
Twisted framework on game server example Rafał Wysocki, Wojciech Zabierowski Abstract – Writing custom server is a complex task. In the beginning it is very important to choose correct tools and technologies. The main aim of this paper was to demonstrate abilities a library set, called Twisted. Twisted is an event-driven asynchronous, network framework written in Python programming language. This document describes basics of Twisted framework and implementation of simple, but efficient, game server on top of Twisted framework. Keywords – Python, Twisted, framework, event-driven, asynchronous, network. I. INDRODUCTION Twisted is an event-driven asynchronous, network engine written in Python programming language licensed under the MIT license. Asynchronous means that program written in the Twisted framework does not block the application when is waiting for data that is not available. Event-driven means that methods and functions are called as a response to certain events, for example when data is received from remote source. Twisted is used by many companies in different projects, for example: • Justin.tv, • Lauchpad, • NASA. Twisted is developed for more than 8 years now, and has more than 1800 unit tests. It is very stable, polished and powerful framework. Twisted was written in Python programming language. Python is a high-level, dynamic script language. It is very powerful language, its key features are: • very clear readable syntax, • intuitive object orientation, • modularity, • high-level, dynamic data types, • extensive standard library [2]. Dynamic nature of Python helps in writing concise and short code. Clear and readable syntax helps in writing code that is easy to read and can be easier to understand.
The most important object in Twisted framework is a twisted.internet.defer.Deferred. It is used to manage callback sequence. In application written in Twisted framework there are always functions or methods attached to Deferred object. When the result of the asynchronous request is available this series of functions or methods are called. When result of the asynchronous request is not available or there was an error, Twisted calls different set of functions, which was attached as so called “errbacks”. Attaching many callbacks and errbacks to one Deferred give us an “callbacks chain” and “errbacks chain”. The first callback in Deferred's callback chain will be called with result, the second will be called with result of the first callback and so on. Error handling in Twisted is modeled after Python exceptions handling. Errbacks are like “except” blocks in regular Python code. If the errback is called instead of the callback object of type twisted.python.failure.Failure is passed to the first errback. Next, if this errback returns data, next callback in the callbacks chain is called, if this errback returns twisted.python.failure.Failure or raises an exception next errback in errbacks chain is called. This situation is illustrated on the figure 1 [1].
II. TWISTED BASICS The core object in every Twisted based application is twisted.internet.reactor. Reactor is the core of event loop in Twisted. The event loop waits and dispatches events. Twisted has many implementations of this class. The specialized implementations are suited for different tasks and are designed to integrate better with particular platforms.
Fig. 1: Data flow in Twisted application
Twisted framework lets you write powerful servers easily. Protocol class or one of its children should be extended in custom server protocol class. Protocol has an “transport” attribute which is a wrapper for socket
2 object. An instance of protocol class is instanced perconnection, and goes away when the connection is finished. This means that persistent configuration should not be kept there. The persistent configuration should be stored in special object called Factory. Factory object should inherit from twisted.internet.protocol.Factory class. One of the simplest servers is shown on the figure 2. This server writes message to every connected client and then close connection. Fig. 4: Orbited architecture from twisted.internet.protocol import Factory, Protocol from twisted.internet import reactor class CustomProtocol(Protocol): def connectionMade(self): self.transport.write(self.factory .nick+'\r\n') self.transport.loseConnection() class CustomFactory(Factory): protocol = CustomProtocol def __init__(self, who=None): self.nick = 'Hello from %s.' % who reactor.listenTCP(8000, CustomFactory("Twisted")) reactor.run() Fig. 2: Simple custom server with Twisted
III. ORBITED Long polling allows emulation of data push from server to client. With long polling server does not response to the request immediately. Instead it waits until data is available and keep connection open. When data is sent from the server to the client, client re-requests information from the server so the server always have a waiting request to respond. This gives an illusion of bidirectional communication [4].
Fig. 3: Long polling
Orbited is an proxy server that allows to integrate any server with web application. Orbited provides socketlike objects in the web browser [3].
IV. SERVER IMPLEMNTATION Chain of responsibility is very useful design pattern for implementing servers. It contains source of command objects and series of processing objects. The incoming packages of data can be treated like command objects. Some handlers can act as dispatchers, cable of sending commands in both directions. Implementation of this design pattern is very straightforward in Python, thanks to its dynamic nature and runtime method dispatch mechanism [5]. Servers are often complex applications. Very important is a good choice of data format and protocol. This article will demonstrate an implementation of game server with text protocol using JSON format. JSON is an acronym for JavaScript Object Notation, it is a lightweight text-based open standard designed for data interchange. It represents data (like numbers, strings) and data structures (like arrays and maps). It is delivered from JavaScript which means it can be easily used in web applications. In general JSON syntax is shorter than XML syntax and more readable for humans. Python has the “json” module, in standard library, which allows easy parsing and building JSON objects. Creating our own protocol means that we have to design a communication entities (packets) for our protocol. Packet will be represented by single JSON objects. Those objects will look as follow: {NODE:”NODE”, CMD:”CMD” ARGS:{arg1:“2”, arg2:”abc”}}. There are three keys: “NODE”, “CMD” and “ARGS” in every packet, each key has its own special meaning for the server. “NODE” indicates which handler should be involved in the processing of the packet. If our server implements two different games, each game should be implemented in different nodes. “CMD” indicates which command should by executed by the handler, for example in chat server this could be “login” if we want to log into the chat or “say” if we want to send new message. “ARGS” is a map which holds additional arguments for executed commands, for example for “login” this could be “nick” argument. Every application has functionality that appears in many places. It is very common to write library with this functionality and use this library in our application. There are two very important and useful classes in game server example - NodeDispatcher and Node.
3 NodeDispatcher reads the value of the “NODE” key in packets and redirect these packets to the appropriate handlers. Node class should be extended by every handler. Node contains functionality that allows to call appropriate method of the handler based on the value of “CMD” key in packets. Packet processing is shown on the figure 5.
utilities, tools and classes that simplifies creation of rich internet application. Qooxdoo is written fully in JavaScript, the only thing we need to run Qooxdoo application is fairly modern webbrowser [6]. Client application has to manage socket object available in Orbited library. These socket has a few functions that we have to be aware of: • open(host,port,isBinary=false) – opens new connection, • send(message) – sends data via socket, • onopen – function called when new connection was opened, • onclose(code) – function called when connection was closed, • onread(message) – function called when new data was received [3].
Fig. 5: Packet processing
def handle_SAY(self, args, packet, packetString): room = self.client.room broadcastLineToClients(room.clients, packetString) Fig. 6: "SAY" command handler Fig. 7: Qooxdoo application
Next important thing is to write handlers for packets in our server. Thanks to the dynamic nature of Python programming language those handlers have very clean and short code, for example method that handles messages send to the chat server is presented in the figure 6. Very important aspect of every serious application is a good code coverage. Python contains unit test module. Unit test module supports everything that is needed to write the good tests, test automation, sharing of setup and shutdown code etc. Trial is Twisted's unit testing framework, it extends standard Python's unit test module. Its key feature is ability to return Deferred object from test method. The test case will not complete until Deferred has fired. If it fires successfully the test passes, otherwise the test fails. This allows easy testing of the asynchronous and event-drivent code. V. CLIENT IMPLEMENTATION Client is implemented in JavaScript using Qooxdoo framework. Qooxdoo framework allows developers to build impressive crossbrowser applications. It contains very long list of ready to use widgets, many
VI. CONCLUSION The main goal of this article was to demonstrate basics of Twisted framework – used to create asynchronous, event-driven application. We can see that good choice of libraries is essential for achieving satisfying results. Thanks to the Twisted framework and high level Python programming language, it is possible to write servers with concise, short, easy extensible and well tested code. Orbited allows to connect to our server from web application. Qooxdoo allows to write rich internet application in plain JavaScript.
REFERENCES [1] http://twistedmatrix.com/trac/ [2] http://python.org [3] http://orbited.org [4] http://en.wikipedia.org/wiki/Push_technology [5] http://en.wikipedia.org/wiki/Chain-ofresponsibility_pattern [6] http://qooxdoo.org/ [7] Marcin Śliwiński, Bartosz Sakowicz, Bartłomiej Swiercz, Andrzej Napieralski: "Implementation of a web
4 hosting service based on J2EE technology", 9th International Conference Modern Problems of Radio Engineering, Telecommunications and Computer Science, TCSET’2008, 19-23 February 2008, Lviv-Slavsko, Ukraine, accepted for publication