I've created a websocket using Python's asyncio
and websockets
modules. This servers works properly in the same machine. This is the actual code for the server:
import sys
import os
import asyncio
import websockets
@asyncio.coroutine
def receive(websocket, path):
data = yield from websocket.recv()
print('< {}'.format(data))
output = 'Sent data from server: {}'.format(data)
yield from websocket.send(output)
print('> {}'.format(output))
start_server = websockets.serve(receive, '127.0.0.1', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
It runs properly, and the connection from a client residing on the same machine connects to it without any problem.
But when I try to access it from a client on a LAN network, it generates a ConnectionRefusedError
. This is the client code:
import asyncio
import websockets
@asyncio.coroutine
def hello():
websocket = yield from websockets.connect(
'ws://192.168.0.26:8765')
try:
name = input("What's your name? ")
yield from websocket.send(name)
print("> {}".format(name))
greeting = yield from websocket.recv()
print("< {}".format(greeting))
finally:
yield from websocket.close()
asyncio.get_event_loop().run_until_complete(hello())
I've installed ufw
on Raspbian to enable the port 8765 with this command:
ufw allow 8765
But it doesn't work. On the Windows machine, the command
nmap -p 8765 192.168.0.26
generates this result:
PORT STATE SERVICE
8765/tcp closed ultraseek-http
And... the command
ufw status
Could someone give some suggestions to solve this communication problem between the client and the server.
Here is one problem:
start_server = websockets.serve(receive, '127.0.0.1', 8765)
You have told websockets to listen only on 127.0.0.1, thus you can only receive connections originating from the local host, and only on legacy IPv4. Both localhost IPv6 connections (the default) and all connections from other computers will receive the connection refused error.
If you want to receive connections from outside the local machine, you should set the Host
to None
or the empty string. This will accept connections from anywhere, on both IPv6 and IPv4, subject of course to any firewall rules.
start_server = websockets.serve(receive, None, 8765)
The host and port are passed directly to asyncio.create_server()
which documents Host as:
- If host is a string, the TCP server is bound to a single network interface specified by host.
- If host is a sequence of strings, the TCP server is bound to all network interfaces specified by the sequence.
- If host is an empty string or None, all interfaces are assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6).