Camel not receiving messages from websocket - python

I am new to websockets and I created a spring boot application to receive websocket messages using Camel. The websocket server was created using Python. I have tested the server using PieSocket on Chrome and was able to receive the messages. However, I am having trouble receiving messages on the camel application. Below are my codes for both the server and client.
Python websocket server
import asyncio
import websockets
# create handler for each connection
async def handler(websocket, path):
while True:
greeting = f"Hello user!"
await websocket.send(greeting)
print(f"> {greeting}")
await asyncio.sleep(10)
start_server = websockets.serve(handler, "localhost", 8000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Java client
package example.org.websocket.route;
import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class DataRoute extends RouteBuilder {
#Override
public void configure() {
from("websocket://localhost:8000")
.log("Received message: ${body}");
}
}
Any help would be useful. Thank you!

Related

Porting a Websocket connection from a (game) website to python

There is some game that communicates with the server via a Websocket connection. I want to simulate this connection in python. When I click on the link, in the network tab, I see these connections: Image.
I copy the first message that the client sends in base64 format and try to reproduce it in code:
import asyncio, base64
from websockets import connect
URL = "wss://c7.eu.tankionline.com:9090/"
MSG_1 = base64.b64decode("ACoAA1TOlEGHY2d6XOx8gfqrE53STCBraCMoiOob+n2N6U10AAAAAAX2kcw=")
async def setup():
async with connect(URL) as websocket:
await websocket.send(MSG_1)
resp = await websocket.recv()
print(resp)
asyncio.run(setup())
But there is no response from the server. Why is that?

Python websockets vs websocket

I'm connecting to the same websocket address but for some reason I can't receive data using websockets+asyncio.
However, it does work when using websocket as well as using a raw websocket connection with Postman.
if SOCKET is the address
Using websockets + asyncio
import asyncio
import websockets
SOCKET = 'wss://api...'
async def handle(uri):
async with websockets.connect(uri) as websocket:
while True:
print(await websocket.recv())
asyncio.get_event_loop().run_until_complete(handle(SOCKET))
Using websocket
from websocket import create_connection
ws = create_connection(SOCKET)
while True:
try:
result = ws.recv()
print(result)
Does anyone know what can possibly be wrong with the first option? I'm actually following a python sample request suggested by a site's documentation when using websockets+asyncio.

python websockets, multiple requests, why only requests are received?

I am trying to test out if I send out multiple requests at the same moment using coroutine can cause the server side receives corrupted data.
My test is based on the sample code from: https://websockets.readthedocs.io/en/stable/intro.html
Somehow, for the following code, the server side only receive one requests? Anyone has some insights? thx
server (this is basically the same code from the websockets Getting Started webpage):
#!/usr/bin/env python3
# WS server example
import asyncio
import websockets
async def hello(websocket, path):
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
start_server = websockets.serve(hello, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Client, I created 1000 tasks, and schedule to run them as soon as possible:
#!/usr/bin/env python3
# WS client example
import asyncio
import websockets
uri = "ws://localhost:8765"
connection = None
async def hello():
global connection
name = "What's your name? "
await connection.send(name)
print(f"> {name}")
async def main():
global connection
connection = await websockets.connect(uri)
#asyncio.run(main())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.run_until_complete(asyncio.wait(
[hello() for i in range(1000)], return_when=asyncio.ALL_COMPLETED
))
UPDATE
The solution is to use a loop.
I found the reason: the server side, handler should use a loop so that the corroutine will not finish immediately after received the first request.
The documentation you linked also includes this paragraph just below the server code:
On the server side, websockets executes the handler coroutine hello once for each WebSocket connection. It closes the connection when the handler coroutine returns.
The client code you linked creates one connection and sends messages on that connection. After the client sends the first message, the server closes the connection, so the next 999 messages you attempt to send are being sent on a closed connection.
If you update the hello handler to include a loop, you will see all messages.
import asyncio
import websockets
async def hello(websocket, path):
while True:
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
start_server = websockets.serve(hello, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Python - Unidirectional websocket

I'm trying to create a unidirectional websocket connection between the client and server (python). The libraries I've currently been prototyping with are websockets and simplesocketserver. I've got a hello world example getting from the server to the client, but I need to be able to send data from the backend to the client unprompted from the client. All of the websockets examples seem to show the server listening to the client and then responding.
So far I've tried:
Using websockets 8.0, sending data from server to client unprompted, this works but only with hard-coded strings, I don't understand how to send real data on demand unprompted from the client
Using simplesocketserver in the same exact manner
Started investigating server sent events - is this more appropriate?
Example from the websockets documentation:
import asyncio
import websockets
async def hello(websocket, path):
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
start_server = websockets.serve(hello, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Note: the need for unidirectional communication is due to existing architecture.
Any guidance or resources on this would be great, I hope I'm overlooking something easy. Thank you!
I came across a similar issue. After some trial and error I found a solution that works for me, maybe so it does for you. I've tested this on Linux and with Firefox and mobile Safari (parallel).
The InputThread waits for input (words) on the command line and writes them into a list, that is sent to all connected clients each time a new string is appended or a client is connected.
Code snippet
import asyncio
import websockets
import json
from threading import Thread
words = []
clients = []
async def register_client(websocket, path):
# register new client in list and keep connection open
clients.append(websocket)
await send_to_all_clients()
while True:
await asyncio.sleep(10)
async def send_to_all_clients():
global words
for i, ws in list(enumerate(clients))[::-1]:
try:
await ws.send(json.dumps({"words": words}))
except websockets.exceptions.ConnectionClosedError:
# remove if connection closed
del clients[i]
class InputThread(Thread):
def run(self):
global words
async def sending_loop():
while True:
i = input()
if not i.strip():
continue
words.append({"options": i.strip().slit()})
await send_to_all_clients()
asyncio.run(sending_loop())
InputThread().start()
asyncio.get_event_loop().run_until_complete(
websockets.serve(register_client, "localhost", 8765))
asyncio.get_event_loop().run_forever()

Either the websocket or the tornado goes down everytime.

I am new to asynchronous programming. I have been using python 3.5 asyncio for a few days. I wanted to make a server capable of receiving data from a websocket machine client (GPS) as well as rendering a html page as the browser client for the websocket server. I have used websockets for the connection between my machine client and server at port 8765. For rendering the webpage I have used tornado at port 8888 (The html file is at ./views/index.html ). The code works fine for only the websocket server. When I added the tornado server, the code behaved weird and I don't know why. There must be something with the asyncio usage. If I place
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
just before
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
, the websocket server doesn't connect. If I do the reverse, the tornado server doesn't run.
Please help me out as I am new to asynchronous programming. The server.py, index.html and the client.py (machine clients) are given below.
server.py
#!/usr/bin/env python
import tornado.ioloop
import tornado.web
import asyncio
import websockets
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("./views/index.html", title = "GPS")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
clients = []
async def hello(websocket, path):
clients.append(websocket)
while True:
name = await websocket.recv()
print("< {}".format(name))
print(clients)
greeting = "Hello {}!".format(name)
for each in clients:
await each.send(greeting)
print("> {}".format(greeting))
start_server = websockets.serve(hello, 'localhost', 8765)
print("Listening on *8765")
app = make_app()
app.listen(8888)
print("APP is listening on *8888")
tornado.ioloop.IOLoop.current().start()
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
client.py
#!/usr/bin/env python
import serial
import time
import asyncio
import websockets
ser =serial.Serial("/dev/tty.usbmodem1421", 9600, timeout=1)
async def hello():
async with websockets.connect('ws://localhost:8765') as websocket:
while True:
data = await retrieve()
await websocket.send(data)
print("> {}".format(data))
greeting = await websocket.recv()
print("< {}".format(data))
async def retrieve():
data = ser.readline()
return data #return the location from your example
asyncio.get_event_loop().run_until_complete(hello())
asyncio.get_event_loop().run_forever()
./views/index.html
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<script>
var ws = new WebSocket("ws://localhost:8765/"),
messages = document.createElement('ul');
ws.onopen = function(){
ws.send("Hello From Browser")
}
ws.onmessage = function (event) {
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
</script>
You can only run one event loop at a time (unless you give each one its own thread, but that's significantly more complicated). Fortunately, there's a bridge between Tornado and asyncio to let them share the same IOLoop.
Early in your program (before any tornado-related code like app = make_app()), do this:
import tornado.platform.asyncio
tornado.platform.asyncio.AsyncIOMainLoop().install()
and do not call IOLoop.current().start(). This will redirect all Tornado-using components to use the asyncio event loop instead.

Categories

Resources