I am using the sanic websocket example to use websocket. I just want to send data to the browser, but the example calls the recv function. How should I remove the recv and continue to send data to the browser?
After removing recv, the browser can't receive data, and there is no way to transfer data later.
Keep recv, the first time the data browser is not received, of course, the next time will not be sent.
Keep recv, the browser will reply to any data after receiving the first sent data, and then I can send the following data.
In these cases, sanic will return to 403. And did not give any tips.
This is my code:
from sanic import Sanic, response
from sanic_cors import CORS
from sanic.websocket import WebSocketProtocol
import time
@api.websocket('/devices/values')
async def feed(request, ws):
while True:
logger.debug("sending data.")
await ws.send(json.dumps(data))
recv_data = await ws.recv()
logger.debug("recv data [%s].", recv_data)
time.sleep(10)
According to the principle of websocket I just checked, this should not happen, so can someone give me some advice?
Thanks!
You definitely do not have to have bi-directional communication. You can implement just push events by not calling receive. I'm writing from my phone, but I'll post a snippet when I am back online.
@FishEatingCat
If you only want to send data, you can try this:
import asyncio
import ujson
from sanic import Sanic
from sanic.log import logger
app = Sanic()
@app.websocket('/ws')
async def feed(request, ws):
while True:
logger.debug("sending data.")
data = {'foo': 'bar'}
await ws.send(ujson.dumps(data))
await asyncio.sleep(10)
if __name__ == "__main__":
app.run()
But just like you said
- After removing recv, the browser can't receive data, and there is no way to transfer data later.
- Keep recv, the first time the data browser is not received, of course, the next time will not be sent.
- Keep recv, the browser will reply to any data after receiving the first sent data, and then I can send the following data.
Because await ws.recv() will keep waiting until there is incoming data.
So, let's do a little trick here:
import asyncio
import async_timeout
import ujson
from sanic import Sanic
from sanic.log import logger
app = Sanic()
@app.websocket('/ws')
async def feed(request, ws):
data = {'foo': 'bar'}
while True:
try:
with async_timeout.timeout(5):
data = await ws.recv()
logger.debug("recv data {}.".format(data))
except:
pass
logger.debug("sending data {}.".format(data))
await ws.send(ujson.dumps(data))
if __name__ == "__main__":
app.run(debug=True)
The log will be:
[2019-04-30 13:45:04 +0800] [1876] [DEBUG]
Sanic
Build Fast. Run Fast.
[2019-04-30 13:45:04 +0800] [1876] [INFO] Goin' Fast @ http://127.0.0.1:8000
[2019-04-30 13:45:04 +0800] [1880] [INFO] Starting worker [1880]
[2019-04-30 13:45:14 +0800] [1880] [DEBUG] sending data {'foo': 'bar'}.
[2019-04-30 13:45:19 +0800] [1880] [DEBUG] sending data {'foo': 'bar'}.
[2019-04-30 13:45:24 +0800] [1880] [DEBUG] sending data {'foo': 'bar'}.
[2019-04-30 13:45:29 +0800] [1880] [DEBUG] sending data {'foo': 'bar'}.
[2019-04-30 13:45:31 +0800] [1880] [DEBUG] recv data {"new": "message"}.
[2019-04-30 13:45:31 +0800] [1880] [DEBUG] sending data {"new": "message"}.
[2019-04-30 13:45:36 +0800] [1880] [DEBUG] sending data {"new": "message"}.
[2019-04-30 13:45:41 +0800] [1880] [DEBUG] sending data {"new": "message"}.
[2019-04-30 13:45:46 +0800] [1880] [DEBUG] sending data {"new": "message"}.
This implement can always send data even there is no incoming data but also capable to receive data if you need it.
Can this solve your problem?
Thank you very much for your reply! @chenjr0719 @ahopkins
I am sorry to reply so long.
I have tested and replaced time.sleep(10)with asyncio.sleep(10) without waiting for data to be received.
I don't need to accept any data, so this is enough.
And then I used zeroMQ to update the data. The websocket just sends data to the page.
So this is over, thank you!
Most helpful comment
Thank you very much for your reply! @chenjr0719 @ahopkins
I am sorry to reply so long.
I have tested and replaced
time.sleep(10)withasyncio.sleep(10)without waiting for data to be received.I don't need to accept any data, so this is enough.
And then I used zeroMQ to update the data. The websocket just sends data to the page.
So this is over, thank you!