0

I am trying to write a client/server apps using websocket. I am thinking about using Autobahn websocket as my communication medium. The client is going to send a command to the server to perform a task and then wait for a series of progress response from the server. In the server, after I receive the command from client, I perform a series of tasks and then call self.sendMessage ("percent completed") % (percent) to the client. The problem I ran into is that sendMessage appear to buffered up all the messages and then sent them all at once at the end. Any idea on how I can solve this problem? Here is the code snippet from the websocket/example/echo/server.py:

import sys 
import time

from twisted.internet import reactor
from twisted.python import log 
from twisted.web.server import Site
from twisted.web.static import File

from autobahn.websocket import WebSocketServerFactory, \
                               WebSocketServerProtocol, \
                               listenWS

class EchoServerProtocol(WebSocketServerProtocol):

   def onMessage(self, msg, binary):
      self.sendMessage("server respond message 1", binary)
      time.sleep (2) 
      self.sendMessage("server response message 2", binary)
      time.sleep (2) 
      self.sendMessage("server response message 3", binary)

I expect the client to receive a message from the server every 2 seconds instead it gets all three messages at once.

2 Answers2

0

time.sleep will block the Twisted reactor. That's (almost) never a good idea. Twisted has reactor.callLater to delay in a non-blocking way.

You can checkout the example here, to assure yourself that Autobahn sends out message immediately.

oberstet
  • 21,353
  • 10
  • 64
  • 97
  • I put time.sleep there for testing only. My point is that after each self.sendMessage() is called, the data should be already sent to the client before the server going into sleep. But my client does get the messages until all three self.sendMessage() calls is completed in the server sample code. It appears to me that it buffers things up before sending the messages at once. Is that some flush call that I can make or configuration that I can call to make the data to be sent immediately? I tried the broadcast example you point out to me and I has the same issue. I – user2860333 Oct 09 '13 at 20:36
  • again: a) `time.sleep` will block the reactor (which is the problem with your code) and b) the broadcast example works. you are free to ignore me;) – oberstet Oct 09 '13 at 21:32
  • I am not ignoring you, believe me. I really appreciate your help. It sounds like if you make multiple calls to sendMessage() within the same function, they are going to get sent all at once after the function is return and reactor has gained control, right? If so, is there anyway I can force the sendMessage to send data across the wire immediately. I did modify the tick() routine in broadcast and added more calls to self.broadcast("some random msg") and the actual messages didn't get sent until the routine return and reactor gains control again. I need the server message in real time. – user2860333 Oct 09 '13 at 22:23
0

I had the same problem with you, after read websocket protocol specific, I have a solution:

self.sendMessage(msg, binary, fragmentSize=len(msg))

from websocket protocol RFC 6455

The primary purpose of fragmentation is to allow sending a message that is of unknown size when the message is started without having to buffer that message. If messages couldn’t be fragmented, then an endpoint would have to buffer the entire message so its length could be counted before the first byte is sent. With fragmentation, a server or intermediary may choose a reasonable size buffer and, when the buffer is full, write a fragment to the network.