|
Tutorials
Various tutorials and code samples
Featured TutorialsThis page should get you started on pylacewing development via various tutorials and code samples Installing pylacewingDependenciesFirst off, you should get the latest Python version. Don't use Python 3.x since pylacewing doesn't work with it and neither does Twisted (AFAIK). Once Python is installed, install Twisted (Twisted also depends on zope.interface, so in case you get errors about that, install it). Next up, get the newest pylacewing release and install it by the usual "python setup.py install"-method. ServerCreating a minimal serverFirst off, we're gonna import the Twisted reactor and the vital pylacewing stuff. Basically, a ServerProtocol instance is a unique connection, and a ServerFactory instance is the actual "server". The ServerDatagram class handles UDP packets. The ServerFactory is and should be responsible for managing things between clients. from twisted.internet import reactor from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram Then, we're going to subclass ServerProtocol and ServerFactory so we can change their functionality (even though for this tutorial, we're not going to do anything: we'll do that in another tutorial). class MyProtocol(ServerProtocol):
pass
class MyFactory(ServerFactory):
protocol = MyProtocolNow we're going to actually run the server by first instantiating the factory, then make it listen on port 6121 (for both TCP and UDP - the Lacewing protocol requires both), and finally, run the reactor: newFactory = MyFactory() reactor.listenTCP(6121, newFactory) reactor.listenUDP(6121, ServerDatagram(newFactory)) reactor.run() Full code: from twisted.internet import reactor
from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram
class MyProtocol(ServerProtocol):
pass
class MyFactory(ServerFactory):
protocol = MyProtocol
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()Congratulations! Your very first server should be up and running now! Sending server messagesTo send messages to peers, we can use the ServerProtocol.sendMessage method: http://mp2.dk/pylacewing/docs/lacewing.server.ServerProtocol-class.html#sendMessage So, the first argument is the message to send, second is subchannel, and the rest are optional (asDatagram will send the message via UDP if it has been enabled). from twisted.internet import reactor
from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram
class MyProtocol(ServerProtocol):
def connectionAccepted(self, hello):
# fired when a new peer connection
# has been accepted
self.sendMessage('Hello', 1)
class MyFactory(ServerFactory):
protocol = MyProtocol
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()This will send the string message "Hello" on subchannel 1 to connecting peers. Receiving peer messagesTo handle messages sent directly to the server, we override the ServerProtocol.messageReceived method: http://mp2.dk/pylacewing/docs/lacewing.server.ServerProtocol-class.html#messageReceived The argument passed to the method is a ClientMessage instance that has the following attributes:
The following server example will echo back messages sent to it: from twisted.internet import reactor
from lacewing.server import ServerProtocol, ServerFactory
class MyProtocol(ServerProtocol):
def messageReceived(self, message):
print 'Received:', message.value, 'on', message.subchannel
self.sendMessage(message.value, message.subchannel)
class MyFactory(ServerFactory):
protocol = MyProtocol
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()Iterating over all peersTo iterate over all peers connected to the server, we have to access the ServerFactory.connections dict. The following server example will send a message to all peers when a new peer connection has been accepted: from twisted.internet import reactor
from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram
class MyProtocol(ServerProtocol):
def connectionAccepted(self, hello):
self.factory.sendGlobal()
class MyFactory(ServerFactory):
protocol = MyProtocol
def sendGlobal(self):
for peer in self.connections.values():
peer.sendMessage('Peer connected', 1)
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()Simulating lagSometimes, it might be a good idea to simulate lag between a server and a client to properly implement client-side prediction or likewise. This can be done by delaying the amount of time it takes for data to arrive at the server, by hooking into the dataReceived method of protocols (for more info, see Twisted documentation). Here's some code that does exactly that: LATENCY = 1 # in seconds
from twisted.internet import reactor
from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram
class MyProtocol(ServerProtocol):
def dataReceived(self, data):
reactor.callLater(LATENCY, ServerProtocol.dataReceived, self, data)
class MyFactory(ServerFactory):
protocol = MyProtocol
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()Disconnecting clientsTo disconnect a client, you can use the ServerProtocol.disconnect method: http://mp2.dk/pylacewing/docs/lacewing.server.ServerProtocol-class.html#disconnect disconnect() accepts some optional arguments (including a string reason for denial). The first argument is the "response" argument, which indicates which request this is a response to. They have the following names:
The constants can be imported from lacewing.constants. The second parameter is the string denial reason - useful for telling the back-end application what went wrong. Some of the responses have obligatory parameters - check the source for more info. The following example will disconnect a peer if it tries to use the name "Moderator" from twisted.internet import reactor
from lacewing.constants import SET_NAME
from lacewing.server import ServerProtocol, ServerFactory, ServerDatagram
class MyProtocol(ServerProtocol):
def acceptLogin(self, name):
# called when a peer is trying to login
# with a name. Return False to ignore.
if name == 'Moderator':
self.disconnect(SET_NAME, 'Invalid name!')
return False
class MyFactory(ServerFactory):
protocol = MyProtocol
newFactory = MyFactory()
reactor.listenTCP(6121, newFactory)
reactor.listenUDP(6121, ServerDatagram(newFactory))
reactor.run()XXX finish :) |