2

When using time.sleep(1) before sendMessage, the hole process stops (even the others connections).

def handleConnected(self): print self.address, 'connected' for client in clients: time.sleep(1) client.sendMessage(self.address[0] + u' - connected')

Server: https://github.com/dpallot/simple-websocket-server

How to solve it?

2 Answers 2

3

The server that you are using is a synchronous, "select" type server. These servers use a single process and a single thread, they achieve concurrency through the use of the select() function to efficiently wait for I/O on multiple socket connections.

The advantage of select servers is that they can easily scale to very large number of clients. The disadvantage is that when the server invokes an application handler (the handleConnected(), handleMessage() and handleClose() methods for this server), the server blocks on them, meaning that while the handlers are running the server is suspended, because both the handlers and the server run on the same thread. The only way for the server to be responsive in this type of architecture is to code the handlers in such a way that they do what they need to do quickly and return control back to the server.

Your handleConnected handler function is not a good match for this type of server, because it is a long running function. This function will run for several seconds (as many seconds as there are clients), so during all that time the server is going to be blocked.

You can maybe work around the limitations in this server by creating a background thread for your long running task. That way your handler can return back to the server after launching the thread. The server will then regain control and go back to work, while the background thread does that loop with the one second sleeps inside. The only problem you have to consider is that now you have sort of a home-grown multithreaded server, so you will not be able to scale as easily.

Another option for you to consider is to use a different server architecture. A coroutine based server will support your handler function as you coded it, for example. The two servers that I recommend in this category are eventlet and gevent. The eventlet server comes with native WebSocket support. For gevent you have to install an extension called gevent-websocket.

Good luck!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much for the explanation! Gonna try something client-side.
1

You are suspending the thread with sleep and the server which you are using seems to be using select to handle the requests not threads. So no other request will be able to be handled.

So you can't use time.sleep.

Why do you need to sleep? Can you solve it some other way?

Maybe you can use something like threading.Timer()

def sendHello(client):
    client.sendMessage("hello, world")

for client in clients:
    t = Timer(1.0, lambda: sendHello(client))
    t.start() # after 30 seconds, "hello, world" will be printed

This is off the top of my head. You would also need a way to cancel each timer so I guess you would need to save each t in a list and call it when done.

3 Comments

Because there's a loop in a function, and I need to send each 1 second the value. Ex: def smth(): for num in range(50, 1500): time.sleep(1) client.sendMessage...
@user3211337 I naively thought that it would be easy adding a thread to make periodic calls. It's a bit more complicated and not really sure if it's posible. To wait one would have to suspend the handleMessage function for a specific client, but I don't think it's feasible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.