start server socket in a woker and consumer PYTHON ASYNCIO - python

With a worker I want to run an asyncio server which will be ready to listen.
asyncio.create_task(self.consumer())
await asyncio.gather(
self.obj_Coinbase.manage_connection(), self.obj_server.run()
)
In the coinbase connection i am receiving data i real time and i would like to send this data with my server.
async def run(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((self.host, self.port))
server.listen(8)
socket_client, adr = await self.loop.sock_accept(server)
while True:
self.clients_sessions.append(sock)
await self.loop.sock_sendall(self.current_client ,
(json.dumps(self.current_data).encode())) # return Task obj
self.last_data_rcv = self.current_data
it doesnt work when i want to lunch server to distrubte the data
The server blocks the reception of the data from the provider coinbase
thanks

Related

How to handle websocket traffic in Python Websocket?

I can use websockets in my code and i can easily store it some list. Here is code
import websockets
import asyncio
clients = {}
async def handle_connection(websocket, path):
# save websocket connection in clients dictionary
clients[websocket] = path
try:
# messages from client
async for message in websocket:
for to_client in clients.keys():
dest_username = clients[to_client]
source_username = clients[websocket]
text_data = message
if source_username == dest_username:
await to_client.send(f"{source_username}: {text_data}")
except Exception as e:
print(e)
finally:
# remove websocket connection
clients.pop(websocket)
# websocket server port
PORT = 5678
start_server = websockets.serve(handle_connection, 'localhost', PORT)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
My question is this, is it the correct way to store all websockets in a list ? Because i can not find any example for storing websockets.Some adviced tornado.But are there any best(optimal) solution ? Thank you for your answers

TCP client reconnect to server if the server is down (using Asyncio)

I am writing a program using asyncio in python where a Client connects to a server, they exchange some messages and the Server closes the connection.
What I also need to implement is a retry mechanism, where in case the server is down the client will keep trying to reconnect every 5 seconds.
Being new in python and with the asyncio concept in general, I need help to understand how to implement that.
Below is a snippet of my code where I start the connection with the server and where I handle it in case of socket closure on server side.
async def main():
# Get a reference to the event loop as we plan to use
# low-level APIs.
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO,
datefmt="%H:%M:%S")
executor1 = concurrent.futures.ThreadPoolExecutor(max_workers=2)
future1 = executor1.submit(init_thread)
loop = asyncio.get_running_loop()
on_con_lost = loop.create_future()
message = future1.result()
message = struct.pack(">I", len(message)) + bytes(message, "utf-8")
transport, protocol = await loop.create_connection(
lambda: EchoClientProtocol(message, on_con_lost),
'127.0.0.1', 9000)
# Wait until the protocol signals that the connection
# is lost and close the transport.
try:
await on_con_lost
finally:
transport.close()
asyncio.run(main())

Python asyncio - starting coroutines in an infinite loop

I am making a simple server/client chat program in Python. This program should allow for multiple users to connect at once, and then execute their requests concurrently. For this, I am using the asyncio module and sockets.
async def accept_new_connections(socket):
socket.listen(1)
while True:
connection, client_address = sock.accept()
print("accepted conn")
asyncio.create_task(accept_commands(socket, connection))
async def accept_commands(socket, connection):
print("accept cmd started")
while True:
# get and execute commands
def main():
asyncio.run(accept_new_connections(socket))
main()
What I would hope to do is running accept_commands for each of the connections, which would then execute commands concurrently. However, the current code only starts accept_commands for the first connection, and blocks the while loop (the one in accept_new_connections).
Any idea what I need to change to have accept_command started for each of the connections instead?
It is tough to tell because your example does have the implementation of accept_commands, but based on your issue it is likely you need to use the async socket methods on event loop itself so that your coroutine can yield execution and let something else happen.
The below example shows how to do this. This starts a socket on port 8080 and will send back any data it receives back to the client. You can see this work concurrently by connecting two clients with netcat or telnet and sending data.
import asyncio
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('localhost', 8080))
socket.listen(1)
socket.setblocking(False)
loop = asyncio.new_event_loop()
async def main():
while True:
connection, client_address = await loop.sock_accept(socket)
print('connected')
loop.create_task(accept_commands(connection))
async def accept_commands(connection):
while True:
request = await loop.sock_recv(connection, 16)
await loop.sock_sendall(connection, request)
loop.run_until_complete(main())

How to structure listen and disseminate with asyncio websockets?

I'm trying to write a server using asyncio/websockets that listens to a single websocket connection on one port, and when it gets a message, it sends that to all of the websockets that are listening to it on a separate port. There could be hundreds of clients on the second port, so I know I need to use the non-blocking await websocket.send(msg). But I can't figure out how to structure this listen/disseminate paradigm in terms of the event loops.
Here's my first attempt:
import asyncio
import websockets
import time
LISTEN_PORT = 8080
SPEAK_PORT = 8081
audience = []
async def add_audience_member(websocket, path):
global audience
print('New audience member!')
audience.append(websocket)
async def add_source(websocket, path):
global audience
while True:
msg = await websocket.recv()
for ws in audience:
await ws.send(msg + ' ' + str(time.time()))
loop = asyncio.get_event_loop()
loop.run_until_complete(websockets.serve(add_audience_member, HOST, SPEAK_PORT))
loop.run_until_complete(websockets.serve(add_source, HOST, LISTEN_PORT))
loop.run_forever()
Then I have a client running:
from websocket import create_connection
ws = create_connection('ws://{}:{}'.format(HOST, 8081))
while True:
data = ws.recv(); print data
The problem is that add_audience_member closes the connection as soon as it adds the new websocket to the audience list, so I get the error:
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.

How to create TCP proxy server with asyncio?

I found these example with TCP client and server on asyncio: tcp server example. But how to connect them to get TCP proxy server which will be receive data and send it to other adress?
You can combine both the TCP client and server examples from the user documentation.
You then need to connect the streams together using this kind of helper:
async def pipe(reader, writer):
try:
while not reader.at_eof():
writer.write(await reader.read(2048))
finally:
writer.close()
Here's a possible client handler:
async def handle_client(local_reader, local_writer):
try:
remote_reader, remote_writer = await asyncio.open_connection(
'127.0.0.1', 8889)
pipe1 = pipe(local_reader, remote_writer)
pipe2 = pipe(remote_reader, local_writer)
await asyncio.gather(pipe1, pipe2)
finally:
local_writer.close()
And the server code:
# Create the server
loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_client, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

Categories