WebSocketServer Written for Python 2.7 Released under the LGPL Kevin Cuzner This is a server meant to run dedicated on a specific port on the host machine. It provides a method to host multiple WebSocket-based services sorted by directory and provide a (relatively) easy interface for writing additional services. This server utilizes multiprocessing for individual services and threading for handling the client socket operations. Example of operation: - WebSocketServer running on port 12345 of the host machine - User requests ws://localhost:12345/foo/bar/ - WebSocketServer processes the directory and begins looking in its service tree for a process named foo->bar->ws_service.py. If the service isn't found, it looks in the physical directory and attempts to include the ws_service.py file in that directory. If it cannot, a 404 is issued. Additionally, if file doesn't contain a class Service, a 500 is issued. If the service is found and started, the WebSocketServer performs a handshake and passes the incoming socket off to the Service class - User requests ws://localhost:12345/foo/bar - Same as above except the server will look for foo->bar.py to find the Service class A service must implement the Services.Service class which is in the form of a multiprocessing.Process. The class must be named Service. The main method for the service should reside in the run() method. Services are imported to run as though they were in the root directory of the server. Services are provided two multiprocessing.Queues by the WebSocketServer: sendQueue and recvQueue. These queues function as pipes for socket information going to and from the service in the form of WebSockets.WebSocketTransactions. Services should continuously monitor the recvQueue to determine when to add a new client object and when to send data to a client object based on the socketId of the transaction object. The socketId is a unique identifier which is used to map to the actual WebSocketClient object. WebSocketClients are back-linked to the process id of the service process that the client is connected to. Whenever something from the client is sent to the server, a separate thread (a WebSocketManager class) will negotiate receiving the data into a transaction and sending it off to the appropriate service's recvQueue. On the service side of things, sending data to sockets is accomplished by adding a WebSockets.WebSocketTransaction object to the service sendQueue with a socketId matching the socket id of the client that was originally sent to the server. Communication to WebSockets is an event based model with an event being fired when something happens on the client and the data being available in its received queue. Using a multithreaded approach for handling individual clients in each Service is discouraged because of the ease of quickly overwhelming the server resources (imagine 10,000 long lived sockets on a single processes each with its own thread...lots of resources). WebSockets are managed as a group in a separate thread in the main server process to eliminate this problem. Services do not have direct access to the socket object itself due to complications in transferring sockets between processes. Instead, queues are used to communicate with the socket indirectly. An added benefit of this is that the actual WebSockets protocol is handled by the WebSocket managing thread. To send data to a socket, a WebSocketClient.Transaction object should be pushed into the sendQueue of the client. Conversely, received transaction objects will be made available in the recvQueue. Services may implement any model for managing the clients which are connected to the service. A suggestion (which may not be the best for all services) is to create a class which takes in the socket id that is passed to the service when the client connects and keep track of this client object throughout its life (until it receives a close transaction). Then, the service can listen to its recvQueue and send off the transactions to these "local" classes which would have a method for handling the reception of a transaction. The server also provides some limited base classes which can be used to create an event driven model for a service by way of "subscriptions". This system was inspired at least partially by the subscription system used in knockoutjs to create "update" events for normal objects. Services.Subscribable can be inherited by any class wishing to use the subscription system. Documentation on the exact usage of this can be found the Subscribable class itself.