dpallot / simple-websocket-server

A python based websocket server that is simple and easy to use.
951 stars 321 forks source link

Send message from server #26

Closed k0a1a closed 8 years ago

k0a1a commented 8 years ago

What would be the correct way of sending a message from the server (say a notification) to a connected client? The following doesn't seems to work:

class ParallelWebsockets(SimpleWebSocketServer):

    def __init__(self, HOST, WSOCK_PORT, RequestHandlerClass):
        SimpleWebSocketServer.__init__(self, HOST, WSOCK_PORT, RequestHandlerClass)
        self.clients = []

    def serverMessage(self):
        print 'sending server message'
        #print self.clients
        for client in self.clients:
            client.sendMessage('server says Hi')

WebsockInstance = ParallelWebsockets(HOST, WSOCK_PORT, WebsocketHandler)
WebsockInstance.serverMessage()

much obliged

dpallot commented 8 years ago

You need to manage the clients that are connected.

clients = []
class ParallelWebsockets(WebSocket):

def handleMessage(self):
    pass

def handleConnected(self):
   clients.append(self)

def handleClose(self):
   clients.remove(self)

server = SimpleWebSocketServer('', 8000, ParallelWebsockets)
server.serveforever()

Then what you want to do is set up a thread that will send the messages to the clients.

t = threading.Thread(target=send_client)
t.start()

void send_client():
    while True:
        for client in list(clients):
            client.sendMessage('ping')
        time.sleep(1)
k0a1a commented 8 years ago

Thanks for this, I will test and report back.

Eluch commented 8 years ago

I've got to the same issue, and found out that after sending message to the client the output buffer won't flush. Im new in python, but figured out how to do it.:

BroadcasterWebsocketServer.py

#!/usr/bin/python

from threading import Thread
from time import sleep
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer

clients = []
debug = False

class WebsocketBroadcasterHandler(WebSocket):

    def handleMessage(self):
        if debug:
            self.sendMessage(self.data)

    def handleConnected(self):
        if debug:
            print (self.address, 'connected')
        clients.append(self)

    def handleClose(self):
        if debug:
            print (self.address, 'closed')
        clients.remove(self)

class BroadcasterWebsocketServer(Thread):

    def __init__(self, host, port, debugInfo=False):
        Thread.__init__(self)
        self.server = SimpleWebSocketServer(host, port, WebsocketBroadcasterHandler)
        self._isClosed = False
        global debug
        debug = debugInfo
        self.setDaemon(True)

    def start(self):
        super(BroadcasterWebsocketServer, self).start()

    def run(self):
        if debug:
            print ('starting server')
        self.server.serveforever()

    def stop(self):
        if debug:
            print ('closing server')
        self.server.close()
        self._isClosed = True

    def waitForIt(self):
        try:
            while self._isClosed is False:
                sleep(0.1)
        except KeyboardInterrupt:
            pass

    def broadcast(self, msg):
        if isinstance(msg, str):
            msg = unicode(msg, "utf-8")
        for client in clients:
            client.sendMessage(msg)
            while client.sendq:
                opcode, payload = client.sendq.popleft()
                remaining = client._sendBuffer(payload)
                if remaining is not None:
                    client.sendq.appendleft((opcode, remaining))
                    break

To get an idea i wrote an example code too.: (example_ws.py)

#!/usr/bin/python

from BroadcasterWebsocketServer import BroadcasterWebsocketServer
from time import sleep

server = BroadcasterWebsocketServer('', 8080, True)
server.start()

try:
    while True:
        sleep(5)
        print ('sending test')
        server.broadcast("test")
except KeyboardInterrupt:
    pass

#server.waitForIt()
#sleep(2)
#server.stop()

I think I will commit a global solution to this program, so anyone can use it problem free.

PS.: (Sorry for the much edit, but I am unexperienced with markdown, and just realized there is a preview tab :smile: )