I want to send values from a for loop from the client-server but the server only receives the first value and the connection is cut shortly
Client
import asyncio
import websockets
import time
async def message():
async with websockets.connect("ws://-------:5051") as socket:
for i in range(20):
await socket.send(f"{i}")
print(i)
time.sleep(4)
asyncio.get_event_loop().run_until_complete(message())
Server
import asyncio
import websockets
async def consumer_handler(websocket,path):
client_type = await websocket.recv()
print(client_type)
start_server = websockets.serve(consumer_handler,"ws://-------:5051", 5051)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
So, your consumer_handler receives message once and finishes.
You need to add loop.
Try something like this:
async def consumer_handler(websocket, path):
async for msg in websocket:
print(msg)
Related
so I want to establish connection with the server initially then send the data from some other function depending upon the choice of user how do i get this done??
import websockets
import asyncio
async def connect():
#i need some code here to connect to 'ws://127.0.0.1:8000'
async def send_data1(websocket):
...#some code here
await websocket.send(data)
async def send_data2(websocket):
...#some code here
await websocket.send(data)
def main():
name=input()
if name=='xyz':
send_data1()
else:
send_data2()
I have a sanic webserver running websockets, behind the scenes its using the "websockets" library.
Server
from asyncio import sleep
from sanic import Sanic
app = Sanic("websocket test")
#app.websocket("/")
async def test(_, ws):
while True:
data = await ws.recv()
data = await ws.send('Hi')
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000)
Client
import asyncio
import websockets
async def hello():
uri = "ws://localhost:8000"
async with websockets.connect(uri) as websocket:
while iteration:
await websocket.send("Hi")
await websocket.recv()
asyncio.get_event_loop().run_until_complete(hello())
When I remove ws.send('Hi') from the server and await websocket.recv() from the client i can get 58000 messages a second, once I start listening for a response it goes all the way down to 6000 messages a second, I am just curious what is making this run 10x slower when the server responds.
I think the solution here would be to seperate your send and recv into seperate tasks so they can yield concurrently.
async def producer(send):
while True:
await send("...")
await asyncio.sleep(1)
async def consumer(recv):
while True:
message = await recv
print(message)
async def test(request, ws):
request.app.add_task(producer(ws.send)))
request.app.add_task(consumer(ws.recv))
Obviously, this is a very simple example, and at the very least you should use some sort of a Queue for your producer.
But, when you break them into seperate tasks, then your recv is not blocked by send.
I am trying to messing up with Websockets module and after checking the main page:
https://websockets.readthedocs.io/en/stable/intro.html
I did following:
SERVER
# SERVER
import asyncio
import websockets
import nest_asyncio
USERS = {}
async def set_online(websocket, user_name):
USERS[user_name] = websocket
await notify()
async def set_offline(websocket, user_name):
USERS.pop(user_name, None)
await notify()
async def notify():
if USERS:
message = "Online users: {}\n".format(len(USERS))
print (message)
#await asyncio.wait([user.send(message) for user in USERS])
else:
message = "Online users: 0\n"
print (message)
async def server(websocket, path):
user_name = await websocket.recv()
await set_online(websocket, user_name)
try:
async for message in websocket:
for user_name, user_ws in USERS.items():
if websocket == user_ws:
print (f"{user_name}: {message}")
finally:
await set_offline(websocket, user_name)
start_server = websockets.serve(server, "localhost", 3000,
ping_interval=None)
nest_asyncio.apply()
loop = asyncio.get_event_loop()
loop.run_until_complete(start_server)
loop.run_forever()
and also:
CLIENT
# CLIENT
import asyncio
import websockets
import nest_asyncio
async def client(localhost, port):
uri = "ws://{0}:{1}".format(localhost, str(port))
async with websockets.connect(uri) as websocket:
user_name = input("set your name: ")
await websocket.send(f"{user_name}")
while True:
message = input("> ")
if message == "/quit":
break
else:
await websocket.send(message)
host = "localhost"
port = 3000
nest_asyncio.apply()
loop = asyncio.get_event_loop()
loop.run_until_complete(client(host, port))
so all works as expected but I would like to achieve that each user can receive the answer as well from other users.
I found there is a conflict when I want to use websocket.send(message) in for loop async for message in websocket: on SERVER side
The link which I paste above, I think has a solution but I am struggling to figure out how to use it properly in my script.
I believe I need to create two tasks (send and recv) which will work in parallel.
Like:
async def handler(websocket, path):
consumer_task = asyncio.ensure_future(consumer_handler(websocket, path))
producer_task = asyncio.ensure_future(producer_handler(websocket, path))
done, pending = await asyncio.wait([consumer_task, producer_task],return_when=asyncio.FIRST_COMPLETED)
for task in pending:
task.cancel()
the following is displayed on the website which I provided above, just one thing needs to be changed from asyncio.ensure_future to asyncio.create_task. I implemented function handler, producer, consumer, producer_handler and consumer_handler to make it works but no luck.
Could someone provide an example or how this should be set up correctly?
I believe asyncio.create_task should be used on both (SERVER and CLIENT) so they both receive and send at one time.
This is pretty long but I hope someone can help me with it and also maybe my part of script will be handy for someone as well!
In Python, I'm using "websockets" library for websocket client.
import asyncio
import websockets
async def init_sma_ws():
uri = "wss://echo.websocket.org/"
async with websockets.connect(uri) as websocket:
name = input("What's your name? ")
await websocket.send('name')
greeting = await websocket.recv()
The problem is the client websocket connection is disconnected once a response is received. I want the connection to remain open so that I can send and receive messages later.
What changes do I need to keep the websocket open and be able to send and receive messages later?
I think your websocket is disconnected due to exit from context manager after recv().
Such code works perfectly:
import asyncio
import websockets
async def init_sma_ws():
uri = "wss://echo.websocket.org/"
async with websockets.connect(uri) as websocket:
while True:
name = input("What's your name? ")
if name == 'exit':
break
await websocket.send(name)
print('Response:', await websocket.recv())
asyncio.run(init_sma_ws())
In your approach you used a asynchronous context manager which closes a connection when code in the block is executed. In the example below an infinite asynchronous iterator is used which keeps the connection open.
import asyncio
import websockets
async def main():
async for websocket in websockets.connect(...):
try:
...
except websockets.ConnectionClosed:
continue
asyncio.run(main())
More info in library's docs.
I am trying to establish a Web-Socket connection to a server and enter into receive mode.Once the client starts receiving the data, it immediately closes the connection with below exception
webSoc_Received = await websocket.recv()
File "/root/envname/lib/python3.6/site-packages/websockets/protocol.py", line 319, in recv
raise ConnectionClosed(self.close_code, self.close_reason)
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1007, no reason.
Client-side Code Snippet :
import asyncio
import websockets
async def connect_ws():
print("websockets.client module defines a simple WebSocket client API::::::")
async with websockets.client.connect(full_url,extra_headers=headers_conn1) as websocket:
print ("starting")
webSoc_Received = await websocket.recv()
print ("Ending")
Decode_data = zlib.decompress(webSoc_Received)
print(Decode_data)
asyncio.get_event_loop().run_until_complete(connect_ws())
Any thoughts on this?
You use run_until_complete() which completes once you started process. Instead, you should use .run_forever(). It will keep your socket open, until you close it.
EDIT:
You can do something like this:
loop = asyncio.get_event_loop()
loop.call_soon(connect_ws) # Calls connect_ws once the event loop starts
loop.run_forever()
Or:
loop = asyncio.get_event_loop()
loop.run_until_complete(connect_ws())
loop.run_forever()
Or if previous examples didn't succeed, you can try with following code:
import asyncio
#asyncio.coroutine
def periodic():
while True:
print("websockets.client module defines a simple WebSocket client API::::::")
with websockets.client.connect(full_url,extra_headers=headers_conn1) as websocket:
print ("starting")
webSoc_Received = websocket.recv()
print ("Ending")
Decode_data = zlib.decompress(webSoc_Received)
print(Decode_data)
def stop():
task.cancel()
task = asyncio.Task(periodic())
loop = asyncio.get_event_loop()
loop.call_later(5, stop)
try:
loop.run_until_complete(task)
except asyncio.CancelledError:
pass
From what I can tell, your current code will exit after it receives its first message.
Try changing your code to a consumer pattern, as mentioned in the websocket docs here:
https://websockets.readthedocs.io/en/stable/intro.html#common-patterns
import asyncio
import websockets
async def connect_ws():
print("websockets.client module defines a simple WebSocket client API::::::")
async with websockets.client.connect(full_url,extra_headers=headers_conn1) as websocket:
while True:
print ("starting")
webSoc_Received = await websocket.recv()
print ("Ending")
Decode_data = zlib.decompress(webSoc_Received)
print(Decode_data)