I want to send messages between two PCs accessing the internet through different networks. I have already created a firewall rule for the port in the server PC. The code works when both of them are using the same WiFi but not when using different connections.
Server (PC #1)
import asyncio
import websockets
import socket
async def hello(websocket):
name = await websocket.recv()
print(f"<<< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f">>> {greeting}")
async def main():
async with websockets.serve(hello, "", port=8765):
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
Client (PC #2)
import asyncio
import websockets
import socket
async def hello():
uri = "ws://[2a02:8388:8bc7:4d00:1921:8126:966d:8d32]:8765"
#not my real IP
async with websockets.connect(uri) as websocket:
name = input("What's your name? ")
await websocket.send(name)
print(f">>> {name}")
greeting = await websocket.recv()
print(f"<<< {greeting}")
if __name__ == "__main__":
asyncio.run(hello())
I try connect to websocket but i have error:
server rejected WebSocket connection: HTTP 403
but when i try in website it's run like this website:
http://www.epetool.com/websocket/
the code in python 3.9:
import asyncio
import websockets
async def handler(websocket):
while True:
message = await websocket.recv()
print(message)
async def main():
url = "wss://io.dexscreener.com/dex/screener/pairs/h6/1?rankBy[key]=volume&rankBy[order]=desc&filters[buys][h1][min]=100&filters[sells][h1][min]=100&filters[liquidity][min]=500&filters[pairAge][max]=1&filters[chainIds][0]=bsc"
async with websockets.connect(url) as ws:
await handler(ws)
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
I have a stuff to de-serialize and transmit data between two programs
Now I have a problem is that the handler for the daemon will be "Inactive" or "Freezed" after the client connects, everything inside it will stop and only the handler for client works.
import asyncio
import websockets
import concurrent
import sdk_exports
class Server:
def __init__(self):
self.msgs = asyncio.Queue(128)
// Server for Daemon
async def payload_recv(self, ws, path):
while ws.open:
payload = await ws.recv()
self.msgs.put(payload)
// Server for Client
async def ws_evt(self, ws, _):
while ws.open:
if not self.msgs.empty():
payload = self.msgs.get()
await ws.send(sdk_exports.handle(payload))
async def main():
srv = Server()
ws_srv = await websockets.serve(srv.ws_evt, '127.0.0.1', '8328', ping_interval=None)
pl_rcv = await websockets.serve(srv.payload_recv, '127.0.0.1',
'28468', ping_interval=None)
print("Standby. Waiting for connections...")
await asyncio.gather(ws_srv.wait_closed(), pl_rcv.wait_closed())
if __name__ == "__main__":
asyncio.run(main())
Im trying to get work Rabbit MQ queues through AioPika to send messages to Socket Io server and server would send those messages to client based on there SID, UID, etc. Documentation for using rabbitmq on socket is almost non existent. I am able to send messages to exchange with rabbit mq producer but socket io server don’t receive anything. But even if i would receive some message from rabbitmq i don’t now how to send message to the client. Because if i put sio.emit(...) into def main() sio.emit is never reached because web.run_app(app) run constantly in loop.
Im using local rabbit mq. How to make the running app and sending messages so they can run independent. Thank you for every hint and help. Really appreciated.
Socket IO code:
from aiohttp import web
import socketio
import redis
mgr = socketio.AsyncAioPikaManager(channel="Socket io test")
sio = socketio.AsyncServer(client_manager=mgr)
app = web.Application()
sio.attach(app)
async def redis_sio_uid_write(sid):
client = redis.Redis(db=0)
client.set(sid, "uid")
async def redis_sio_uid_delete(sid):
client = redis.Redis(db=0)
client.srem(sid, "uid")
#sio.event
async def connect(sid, environ):
"""Connect and print "connection established" message."""
await redis_sio_uid_write(sid)
print('Connection Established', sid)
#sio.event
async def disconnect(sid):
"""Disconnect and print "disconnected from server" message."""
print('disconnected from server', sid)
def main():
web.run_app(app)
if __name__ == '__main__':
main()
'''
Rabbit MQ Producer:
import sys
import asyncio
from aio_pika import connect, Message, DeliveryMode, ExchangeType
async def main(loop):
# Perform connection
connection = await connect(loop=loop)
# Creating a channel
channel = await connection.channel()
socketio_exchange = await channel.declare_exchange(
"Socket io test", ExchangeType.FANOUT
)
message_body = b"Hello World!"
message = Message(
message_body,
delivery_mode=DeliveryMode.PERSISTENT
)
# Sending the message
await socketio_exchange.publish(message, routing_key="")
print(" [x] Sent %r" % message)
await connection.close()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
ok so i solve the concurrent part with threading but still dont know ho to connect the rabbit mq onto socket io server.
socketio server:
from aiohttp import web
import socketio
import redis
import time
import random
import asyncio
from threading import Thread, Event, Lock
mgr = socketio.AsyncAioPikaManager(channel="Socket io test")
sio = socketio.AsyncServer(client_manager=mgr)
app = web.Application()
sio.attach(app)
loop = asyncio.new_event_loop()
def side_thread(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
thread = Thread(target=side_thread, args=(loop,), daemon=True)
thread.start()
async def redis_sio_uid_write(sid):
client = redis.Redis(db=0)
client.sadd(sid, "".join([str(random.randint(1, 10)) for _ in range(10)]))
async def redis_sio_uid_delete(sid):
client = redis.Redis(db=0)
client.spop(sid)
#sio.event
async def connect(sid, environ):
"""Connect and print "connection established" message."""
await redis_sio_uid_write(sid)
print('Connection Established', sid)
#sio.event
async def disconnect(sid):
"""Disconnect and print "disconnected from server" message."""
await redis_sio_uid_delete(sid)
print('disconnected from server', sid)
async def _data():
while 1:
await sio.emit(event="message_rabbit_mq", data=time.time())
await asyncio.sleep(5)
def main():
future = asyncio.run_coroutine_threadsafe(_data(), loop)
future.add_done_callback(web.run_app(app))
if __name__ == '__main__':
main()
The documentation for your use case is here: Emitting from external processes.
From the documentation, the example for a Redis queue is as follows:
# connect to the redis queue as an external process
external_sio = socketio.RedisManager('redis://', write_only=True)
# emit an event
external_sio.emit('my event', data={'foo': 'bar'}, room='my room')
You would need to replace RedisManager with the aiopika manager, but other than that everything works the same. In case it isn't clear, you do not need to manage anything on the RabbitMQ side, you should use the client manager class both on the server and the external process scripts.
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)