zomgistania

Main page | About | Articles | Previous Posts | Archives

Saturday, September 09, 2006

Writing SSE backends with Python

And here we go again with the snake...

As I mentioned in the last post, I wrote this server script for SSE in Python.

Well, I thought it would be more worthwhile to turn it into a framework kind of thing, on which you can easily build your SSE backends.


Warning: the code and stuff are in Python and I'm not going to go into details about the language here. I'll just describe the functions and classes in the framework.


The basic implementation is built on the Twisted networking framework for Python. If you want to know more about Twisted, you can find their docs from their page.


My framework consists of three classes: the SSEClient, SSEServer and Service classes.

The SSEServer class is the "main" processor. It handles reading the console for input, pinging users and sending requests to the correct Services.


The Service class is what the programmer will be mainly using.


The SSEClient is used as the client for the services. It contains the SSE request and methods to write data to the stream and such.


You can download the framework from here.

An example Service made with the framework can be downloaded from here.

The example service can be run with Python with python sseexample.py. It starts the server in port 3080.


Descriptions of the classes

SSEServer:

example = SSEServer(services,True,True)

the SSEServer takes three parameters:
a dict of the services
True/False if you want it to ping users automatically
True/False if you want it to read console input

the format for the service dict:
{'/service/path': ServiceClass(), '/second/service': SecondClass()}

For example, if you set the path to '/', the service is accessible with http://yourserver:port/ and if you set it to '/example', it's accessible with http://yourserver:port/example.




Service:

example = Service('Service name')

Service takes one parameter: the name of the service. The service itself does nothing, so you will have to make your own class which inherits from it.

Service functions:

parse(request) - this is called when a client wants to access the service. Override in your own class

findClient(request) - can be used to see if the user has already opened an SSE session. Returns the SSEClient if found, otherwise None.

startSession(client) - used to start a new SSE session. Pass an SSEClient as the parameter. After the session is created, it sends the clients session-id. Format:
Event: session-id
data:

broadcast(type,message) - sends a message to all clients. type is the event type and message is the data for the event

ping() - sends a ping to every user who hasn't received a message in the last 60 seconds. Used automatically by the SSEServer pinger.

drop(client) - removes a client from the list. Parameter is an SSEClient


SSEClient

example = SSEClient(service,request)

Parameters for the SSEClient are the "owner" service and the client's request.

You can override the SSEClient so you can add more variables to it, like the users name in a chat or something like that.

functions:

stop(reason) - automatically called when the users connection is closed. Calls the parent services drop method.

sendMsg(type,data) - send a message to the client. type is the event type and data the event data. The data can also be a list and it will be handled properly.




There we go. Feel free to ask if you have anything on your mind.

Labels: , ,

4 Comments:

  • Thought I'd add a reason why using a stand-alone server like this one is better than using a PHP script on the web-server...


    When using a PHP script, you can send the SSE events with it pretty much the same way as with a stand-alone app, but the difference comes in when the user makes a GET request to, say, send a message to a chat.

    First, you'll need a separate script for parsing the GET request which saves the details about it to a database. The SSE stream script has to constantly poll the DB for new data, because there is no way for the separate GET request parser to tell it when there's new data to send.



    With a stand-alone server like this one, the GET requests are parsed by the same process as the SSE streams. Therefore the code parsing the GET requests has direct access to the streams right away and can send events immediately without a need for a database. I also noticed that PHP doesn't notice SSE clients disconnecting as well as this Python script does (at least not on my end) so often you may get "dead" connections hanging around taking processing power.

    By Blogger Jani, at 7:34 AM  

  • Take a look at http://orbited.org, a python server specialized to send Comet events. It handles SSE in Opera, but also has working methods in other browsers.

    By Anonymous Anonymous, at 2:10 PM  

  • Looks interesting. Thanks for letting me know

    By Blogger Jani, at 1:01 PM  

  • "because there is no way for the separate GET request parser to tell it when there's new data to send."

    Not entirely true. The SSE process could be listening for events on a UDP socket or UNIX socket, and relay them to the SSE client. This way the process that takes the GET request, can just send the response via UDP/UNIX, and it would be relayed to the end client.

    By Anonymous Anonymous, at 1:22 AM  

Post a Comment

<< Home