How can I connect with address using asyncio open_connection function - python

I would like to connect with several address using asyncio library, like
'127.0.0.1:8000/hello'
But where can I put '/hello' part ? and how can I call this part? (endpoint? static url? )
asyncio.open_connection('127.0.0.1', 8000)

But where can I put /hello part ?
asyncio.open_connection opens a raw TCP connection to the given remote endpoint. The address of the form 127.0.0.1:8000/hello strongly indicates an HTTP connection. HTTP is a protocol built on top of TCP, where you connect to the given host and port (127.0.0.1 and port 8000 in your case) using TCP and send a request in a specified format, and to which the server answers with a response.
HTTP communication is a complex topic and is not something you want to implement from scratch. Fortunately there are mature asyncio-aware libraries that handle it for you, such as aiohttp. Using that library connecting to a server might look like this:
import aiohttp, asyncio
async def connect_to(url, session):
async with session.get(url) as response:
return await response.data()
async def main():
async with aiohttp.ClientSession() as session:
data = connect_to('http:/127.0.0.1:8000/hello')
# do something with data, or connect to other urls
asyncio.run(main())
and how can I call this part? (endpoint? static url? )
That part is typically called the path of the URL, see e.g. section 3.3 of the RFC for more details.

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?

Will websocket lost data during receiving and sending?

I am using the third-party websocket library of Python
(https://github.com/miguelgrinberg/flask-sock)
it is ran with flask framework
I am sending over a data with 2568 length of characters, the server sometimes can receive full data, sometimes it receive only total length of 1420
The flask web application is running in server, and my data is sending from my localhost pc, i checked with wireshark, my data was successfully send over to server with 2568 length of characters, but my server sometimes receiving only 1420 length of data/string
i just contacted the developer of this third-party library, here is it https://github.com/miguelgrinberg/flask-sock/issues/6
my question is to understanding, will websocket lost data in the middle or i am sending too much sizes of data?
Update #1
Server
from flask_sock import Sock
app = Flask(__name__)
sock = Sock(app)
#sock.route('/websocket/instance_state')
def instance_state(ws):
while ws.connected:
print("Receiving :: ")
req = ws.receive()
print(f"{len(req)}")
ws.send(req)
Client
import websockets
async with websockets.connect(uri) as websocket:
while True:
the_string = "a" * 2600
print(f"Sending :: {the_string}")
await websocket.send(the_string)
resp = await websocket.recv()
I had overcome the situation by implementing Flask-SocketIO instead of Flask-Sock, so the issue was not solved but due to project timeline, Flask-SocketIO works fine

python websockets - how to do a simple synchronous send command?

I'm new to websockets. I've been using the examples on the Getting Started page of the websockets docs, mainly the Synchronization Example.
In this use case, I have a sqlite3 database on localhost. I edit that database from a python GUI program on localhost which just imports the database code layer directly. The client then tells the websocket server to send out some extracted data to all clients.
(Eventually this will be on a LAN, with the server machine running a Flask API.)
This is working, with the code below, but it's not clear if I'm doing it correctly. Basically I want to send websockets messages when certain database activity takes place, and I'm confused about how to do a 'simple' non-async send, when invoked from code, ultimately in response to a GUI interaction, as opposed to doing a send in response to an incoming websocket message. In pseudo-code:
def send(ws,msg):
ws.send(msg)
send(ws,'OK!')
The way I'm accomplishing that is wrapping the async def that does the sending in a non-async 'vanilla' def.
The websocket server code:
# modified from https://websockets.readthedocs.io/en/stable/intro.html#synchronization-example
import asyncio
import websockets
USERS = set()
async def register(websocket):
print("register: "+str(websocket))
USERS.add(websocket)
async def unregister(websocket):
print("unregister: "+str(websocket))
USERS.remove(websocket)
# each new connection calls trackerHandler, resulting in a new USERS entry
async def trackerHandler(websocket, path):
await register(websocket)
try:
async for message in websocket:
await asyncio.wait([user.send(message) for user in USERS])
finally:
await unregister(websocket)
start_server = websockets.serve(trackerHandler, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
in the database interface code (on localhost, this file is just imported directly to the GUI app; but on the LAN server, this is the file specified in the WSGI call in Flask):
import asyncio
import websockets
# uri = "ws://localhost:8765"
# wrap the asynchronous send function inside a synchronous function
def wsSend(uri,msg):
async def send():
async with websockets.connect(uri) as websocket:
# await websocket.send(str.encode(str(msg)))
await websocket.send(json.dumps({"msg":msg}))
# print(f"> {msg}")
# greeting = await websocket.recv()
# print(f"< {greeting}")
asyncio.get_event_loop().run_until_complete(send())
...
...
def tdbPushTables(uri,teamsViewList=None,assignmentsViewList=None,teamsCountText="---",assignmentsCountText="---"):
# uri = "ws://localhost:8765"
if not teamsViewList:
teamsViewList=tdbGetTeamsView()
if not assignmentsViewList:
assignmentsViewList=tdbGetAssignmentsView()
if uri=='pusher':
pusher_client.trigger('my-channel','teamsViewUpdate',teamsViewList)
pusher_client.trigger('my-channel','assignmentsViewUpdate',teamsViewList)
else:
wsSend(uri,json.dumps({
"teamsView":teamsViewList,
"assignmentsView":assignmentsViewList,
"teamsCount":teamsCountText,
"assignmentsCount":assignmentsCountText}))
it's actually the client that initiates the call to tdbPushTables:
def buildLists(self):
self.teamsList=tdbGetTeamsView()
self.assignmentsList=tdbGetAssignmentsView()
self.updateCounts()
tdbPushTables('ws://localhost:8765',self.teamsList,self.assignmentsList,self.teamsCountText,self.assignmentsCountText)
Feels spooky. Is it spooky or is this actually the right way to do it? Should I be using the websockets module for the server, but a different module to do the 'simple'/synchronous sending of the websocket message to the server?
Two known side effects of this solution: 1) it opens and closes the websocket connection on every call - probably not really a problem...?, and 2) it results in non-fatal handled messages like this in the server transcript:
register: <websockets.server.WebSocketServerProtocol object at 0x041C46F0>
Task exception was never retrieved
future: <Task finished coro=<WebSocketCommonProtocol.send() done, defined at C:\Users\caver\AppData\Roaming\Python\Python37\site-packages\websockets\protocol.py:521> exception=ConnectionClosedOK('code = 1000 (OK), no reason')>
Traceback (most recent call last):
File "C:\Users\caver\AppData\Roaming\Python\Python37\site-packages\websockets\protocol.py", line 555, in send
await self.ensure_open()
File "C:\Users\caver\AppData\Roaming\Python\Python37\site-packages\websockets\protocol.py", line 812, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedOK: code = 1000 (OK), no reason
unregister: <websockets.server.WebSocketServerProtocol object at 0x041C46F0>
EDIT: looks like the websocket (singular) module has a synchronous interface, and the websockets (plural) docs explain that if you want to go synchronous you should use a different module; so, this works:
(instead of importing asyncio and websockets)
from websocket import create_connection
def wsSend(uri,msg):
ws=create_connection(uri)
ws.send(json.dumps({"msg":msg}))
ws.close()
It does still result in the same handled traceback showing up in the server transcript each time wsSend is called; there's probably a way to silence that traceback output, but, regardless, it still doesn't seem to affect anything.
Your code feels spooky, because you are mixing async code with synchronous code.
Based on personal experience, the code is simpler to follow if you keep most of the code asynchronous.
The structure will become something like:
import asyncio
import websockets
async def main():
# Create websocket connection
async with websockets.connect(uri) as websocket:
await your_function_that_does_some_processing(websocket)
asyncio.get_event_loop().run_until_complete(main())
Have in mind that big sections of blocking code can generate trouble.

How to get the IP address of a client using aiohttp

I am currently working on a django project where I use aiohttp to communicate between the backend and frontend. I wanted to get the IP address of a client when a request is made from the frontend. Looked in different docs but none seems to point to exactly how to get the IP address using aiohttp. Someone Help!
from aiohttp import web
async def handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
try:
async for msg in ws:
# handle incoming messages
# use ws.send_str() to send data back
...
finally:
task.cancel()
Based on the aiohttp docs you can get the originating IP address of a client initiated HTTP request from requests remote parameter (request.remote).

Manually giving the twisted (web) network stack a packet to process?

I am running an HTTP server using the twisted framework. Is there any way I can "manually" ask it to process some payload? For example, if I've constructed some Ethernet frame can I ask twisted's reactor to handle it just as if it had just arrived on my network card?
You can do something like this:
from twisted.web import server
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientFactory
class SomeWebThing(Resource):
def render_GET(self, request):
return "hello\n"
class SomeClient(Protocol):
def dataReceived(self, data):
p = self.factory.site.buildProtocol(self.transport.addr)
p.transport = self.transport
p.dataReceived(data)
class SomeClientFactory(ClientFactory):
protocol = SomeClient
def __init__(self, site):
self.site = site
if __name__ == '__main__':
root = Resource()
root.putChild('thing', SomeWebThing())
site = server.Site(root)
reactor.listenTCP(8000, site)
factory = SomeClientFactory(site)
reactor.connectTCP('localhost', 9000, factory)
reactor.run()
and save it as simpleinjecter.py, if you then do (from the commandline):
echo -e "GET /thing HTTP/1.1\r\n\r\n" | nc -l 9000 # runs a server, ready to send req to first client connection
python simpleinjecter.py
it should work as expected, with the request from the nc server on port 9000 getting funneled as the payload into the twisted web server, and the response coming back as expected.
The key lines are in SomeClient.dataRecieved(). You'll need a transport object with the right methods -- in the example above, I just steal the object from the client connection. If you aren't going to do that, I imagine you'll have to make one up, as the stack will want to do things like call getPeer() on it.
What is the use-case?
Perhaps you want to create your own Datagram Protocol
At the base, the place where you
actually implement the protocol
parsing and handling, is the
DatagramProtocol class. This class
will usually be decended from twisted.internet.protocol.DatagramProtocol.
Most protocol handlers inherit either
from this class or from one of its
convenience children. The
DatagramProtocol class receives
datagrams, and can send them out over
the network. Received datagrams
include the address they were sent
from, and when sending datagrams the
address to send to must be specified.
If you want to see wire-level transmissions rather than inject them, install and run WireShark, the fantastic, free packet sniffer.

Categories

Resources