Reputation: 91
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 !
Upvotes: 5
Views: 13534
Reputation: 195408
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?
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
Upvotes: 5
Reputation: 91
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())
Upvotes: 2