I've Been searching for quite a long time now and practicing a bit but I can't find a solution.

Here's my goal:

  • I would like a Javascript Client that occasionally sends data to my server

  • I'd like a server (in Python) that periodically (every second or so) sends data to my client.

Here's what I've got:
I'm able to send data to my client and process it as I want.
I'm able to send data to my server but I'm not able to receive it in my Server. It has to be a non-blocking process and because the data is occasionally sent, I'm having trouble implementing this in my server code.

My server code so far is:

import asyncio
import random
import websockets
import json


async def recv(websocket, path):
    try:
        name = asyncio.wait_for(websocket.recv(), timeout=2)
    except TimeoutError:
        print("Time exceeded")
        name = None
    await asyncio.sleep(0.5)


async def send(websocket, path):
    data = [
            {
              "name": "Random Int 1",
              "number": random.randint(0, 1000)
            },
            {
              "name": "Random Int 2",
              "number": random.randint(1001, 2000)
            },
            {
              "name": "Random Int 3",
              "number": random.randint(2001, 3000)
            }
    ]
    await websocket.send(json.dumps(data))
    await asyncio.sleep(0.5)


async def main(websocket, path):
    while True:
        send_task = asyncio.create_task(send(websocket, path))
        recv_task = asyncio.create_task(recv(websocket, path))
        await send_task
        await recv_task

start_server = websockets.serve(main, "localhost", 3500)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

my errors are:

program.py:43: DeprecationWarning: There is no current event loop
  asyncio.get_event_loop().run_until_complete(start_server)
program.py:44: DeprecationWarning: There is no current event loop
  asyncio.get_event_loop().run_forever()
python3.10/asyncio/events.py:80: RuntimeWarning: coroutine 'wait_for' was never awaited
  self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
python3.10/asyncio/events.py:80: RuntimeWarning: coroutine 'WebSocketCommonProtocol.recv' was never awaited
  self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Any tips ? Thanks a lot !

2

There are 2 best solutions below

0
On

Try this server code:

import asyncio
import random
import websockets
import json


async def handler(websocket):

    # create periodic task:
    asyncio.create_task(send(websocket))

    while True:
        try:
            message = await websocket.recv()
            print(message)

        # client disconnected?
        except websockets.ConnectionClosedOK:
            break


async def send(websocket):
    while True:
        data = [
            {"name": "Random Int 1", "number": random.randint(0, 1000)},
            {"name": "Random Int 2", "number": random.randint(1001, 2000)},
            {"name": "Random Int 3", "number": random.randint(2001, 3000)},
        ]

        try:
            await websocket.send(json.dumps(data))

        # client disconnected?
        except websockets.ConnectionClosedOK:
            break

        await asyncio.sleep(0.5)


async def main():
    async with websockets.serve(handler, "localhost", 3500):
        await asyncio.Future()  # run forever


if __name__ == "__main__":
    asyncio.run(main())

How to test it?

  • in one terminal run this server code
  • in other terminal run this python code: python -m websockets ws://localhost:3500

You will immediately see that the server sends every 0.5 seconds some random Json messages. You can type some message and press enter and see that the message is printed in the server screen. To exit client press Ctrl+D

0
On

It seems that I found a working solution but not sure that this is the best...

Here's my code:

import asyncio
import random
import websockets
import json


async def recv(websocket, path):
    try:
        name = await asyncio.wait_for(websocket.recv(), timeout=0.1) #I forgot the "await" \facepalm
        print("name", name)
    except asyncio.TimeoutError:
        print("No Data")
    await asyncio.sleep(0.1)

async def send(websocket, path):
    data = [
            {
              "name": "Random Int 1",
              "number": random.randint(0, 1000)
            },
            {
              "name": "Random Int 2",
              "number": random.randint(1001, 2000)
            },
            {
              "name": "Random Int 3",
              "number": random.randint(2001, 3000)
            }
    ]
    await websocket.send(json.dumps(data))
    await asyncio.sleep(0.1)


async def main2(websocket, path):
    while True:
        send_task = asyncio.create_task(send(websocket, path))
        await send_task
        recv_task = asyncio.create_task(recv(websocket, path))
        await recv_task

#rewrite of this part is to remove Deprecation Warning
async def main():
    server = await websockets.serve(main2, 'localhost', 3500)
    await server.wait_closed()

asyncio.run(main())