Forum Archive

[SOLVED] Is it possible to manage websockets with aiosync and aiohttp ?

Brun0oO

Hi,

This topic follows this one :
https://forum.omz-software.com/topic/3385/solved-how-to-install-greenlet-for-gevent-websocket

If my server and client run on my desktop then it's OK.
But if the same server runs on my ios device and the client stays on my desktop then I got an error code "405 : method not allowed".

Here the code for my websockets server websockets-server.py:

import asyncio
import aiohttp
from aiohttp import web

async def websocket_handler(request):

    ws = web.WebSocketResponse()
    await ws.prepare(request)

    async for msg in ws:
        if msg.tp == aiohttp.MsgType.text:
            if msg.data == 'close':
                await ws.close()
            else:
                ws.send_str(msg.data + '/answer')
        elif msg.tp == aiohttp.MsgType.error:
            print('ws connection closed with exception %s' %
                  ws.exception())

    print('websocket connection closed')

    return ws

app = web.Application()
app.router.add_route('GET', '/', websocket_handler)

loop = asyncio.get_event_loop()
handler = app.make_handler()
f = loop.create_server(handler, '0.0.0.0', 8090)
srv = loop.run_until_complete(f)
print('serving on', srv.sockets[0].getsockname())
try:
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    srv.close()
    loop.run_until_complete(srv.wait_closed())
    loop.run_until_complete(app.shutdown())
    loop.run_until_complete(handler.finish_connections(60.0))
    loop.run_until_complete(app.cleanup())
loop.close()

Here the code for my websocket client (caution, you have to change the ip server address from localhost to the ip address of your ios device) websockets-client.html :

<!DOCTYPE html>

<html lang="en">
<head>
    <title>Websocket Client</title>
    <script src=https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
    </script>  
    <script type="application/javascript">
        var ws;
        var ipserver = "localhost";
        function init() {
            var servermsg = document.getElementById("servermsg");
            var ipservermsg = document.getElementById("ipservermsg");
            ipservermsg.innerHTML = ipservermsg.innerHTML + ipserver;
            ws = new WebSocket("ws://"+ipserver+":8090/");
            ws.onopen = function(){
                servermsg.innerHTML = servermsg.innerHTML + "<br>Server connected";
            };
            ws.onmessage = function(e){
                servermsg.innerHTML = servermsg.innerHTML + "<br><< Received data: " + e.data;
            };
            ws.onclose = function(){
                servermsg.innerHTML = servermsg.innerHTML + "<br>Server disconnected";
            };
        }
        function postmsg(){
            var text = document.getElementById("message").value;
            ws.send(text);
            servermsg.innerHTML = servermsg.innerHTML + "<br>>> Data sent: " + text;
        }
    </script>
</head>
<body onload="init();">
    <div id="ipservermsg"><h1>IP server:</h1></div>
    <div id="Send"><h1>Send:</h1></div>
    <form action="" onSubmit="postmsg();return false;">
        <input type="text" name="message" value="" id="message">
        <input type="submit" name="submit" value="Go!" id="submit">
    </form>
    <div id="servermsg"><h1>Message log:</h1></div>
</body>

</html>

I hope someone will help me...
Brun0oO

ccc

Were you able to do the opposite? i.e. Run the server on your desktop and run the client on iOS?

Brun0oO

@ccc Yes, I can start the client on iOS using Safari and access to my server on my desktop.

Brun0oO

bennr01

@Brun0oO If you only need websockets, you could also use Autobahn|Python, which runs on asyncio and/or Twisted.

Brun0oO

@bennr01 said:

@Brun0oO If you only need websockets, you could also use Autobahn|Python, which runs on asyncio and/or Twisted.

That's the solution, thank you !!

In order to install autobahn, i did under Stash "pip install zope.interface".
As "pip install twisted" failed, i downloaded the twisted code source and moved manually the twisted package to the site-packages folder. Then, i performed a "pip install autobahn".

Here the code for the websocket server websocket-server.py:

from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory

import socket

def get_local_ip_addr(): # Get the local ip address of the device
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Make a socket object
    s.connect(('8.8.8.8', 80)) # Connect to google
    ip = s.getsockname()[0] # Get our IP address from the socket
    s.close() # Close the socket
    return ip # And return the IP address

class MyServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        print("Client connecting: {0}".format(request.peer))

    def onOpen(self):
        print("WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {0} bytes".format(len(payload)))
        else:
            print("Text message received: {0}".format(payload.decode('utf8')))

        # echo back message verbatim
        self.sendMessage(payload, isBinary)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))


if __name__ == '__main__':

    try:
        import asyncio
    except ImportError:
        # Trollius >= 0.3 was renamed
        import trollius as asyncio



    factory = WebSocketServerFactory(u"ws://127.0.0.1:9000")
    factory.protocol = MyServerProtocol

    loop = asyncio.get_event_loop()
    coro = loop.create_server(factory, '0.0.0.0', 9000)
    server = loop.run_until_complete(coro)
    print("Server started at {0}:{sock[1]}".format(get_local_ip_addr(),sock=server.sockets[0].getsockname()))

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.close()
        loop.close()

The code for the websocket client is the same as the previous one.

Brun0oO