Python Tornado WebSocket: not working on second network interface - python

I have WebSocket server and client app running on the same physical server. The server has two network interfaces and two IP addresses. When I run WebSocket server/client on first IP it works perfect. Bit it dosn't work on second.
Server:
port = 8080
ip1 = '192.168.100.11'
ip2 = '10.110.50.11'
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(port, ip1)
With second IP I got the following errors on client:
ERROR:tornado.application:Exception in callback <bound method WebSocketClient.keep_alive of <__main__.WebSocketClient instance at 0x7efc93d912d8>>
Traceback (most recent call last):
File "/opt/python/lib/python2.7/site-packages/tornado/ioloop.py", line 1229, in _run
return self.callback()
File "./client_rt_websocket.py", line 70, in keep_alive
self.ws.write_message("sendHeartbeat 1")
File "/opt/python/lib/python2.7/site-packages/tornado/websocket.py", line 1214, in write_message
return self.protocol.write_message(message, binary=binary)
File "/opt/python/lib/python2.7/site-packages/tornado/websocket.py", line 870, in write_message
raise WebSocketClosedError()
It seems like socket is closed and client cannot write message.

I've resolved the issue by restarting problematic network interface:
ifconfig eno2 down
ifconfig eno2 up

Related

Pyro4 [Errno -2]

I am trying out pyro4 connection between my PC and Raspberry Pi 4.
Code on my PC is:
# saved as server.py
import Pyro4, Pyro4.naming
import socket, threading
# Define an object that will be accessible over the network.
# This is where all your code should go...
#Pyro4.expose
class MessageServer(object):
def show_message(self, msg):
print("Message received: {}".format(msg))
# Start a Pyro nameserver and daemon (server process) that are accessible
# over the network. This has security risks; see
# https://pyro4.readthedocs.io/en/stable/security.html
hostname = socket.gethostname()
ns_thread = threading.Thread(
target=Pyro4.naming.startNSloop, kwargs={'host': hostname}
)
ns_thread.daemon = True # automatically exit when main program finishes
ns_thread.start()
main_daemon = Pyro4.Daemon(host=hostname)
# find the name server
ns = Pyro4.locateNS()
# register the message server as a Pyro object
main_daemon_uri = main_daemon.register(MessageServer)
# register a name for the object in the name server
ns.register("example.message", main_daemon_uri)
# start the event loop of the main_daemon to wait for calls
print("Message server ready.")
main_daemon.requestLoop()
And code on my Raspberry is:
import Pyro4
import sys
print("Message:")
msg=sys.stdin.readline().strip()
message_server = Pyro4.Proxy("PYRONAME:192.168.1.5")
message_server.show_message(msg)
Code on my PC doesn t show any errors, but when I try to send a message from raspberry i get this:
What s your message?
test
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 102, in getIpAddress
return getaddr(config.PREFER_IP_VERSION) if ipVersion is None else getaddr(ipVersion)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 515, in connect_and_handshake
sslContext=sslContext)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 266, in createSocket
if getIpVersion(connect[0]) == 4:
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 68, in getIpVersion
address = getIpAddress(hostnameOrAddress)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 106, in getIpAddress
return getaddr(0)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/pi/Desktop/client.py", line 10, in <module>
message_server.show_message(msg)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 588, in __pyroCreateConnection
uri = _resolve(self._pyroUri, self._pyroHmacKey)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 1915, in _resolve
return nameserver.lookup(uri.object)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
self._pyroGetMetadata()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
self.__pyroCreateConnection()
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 596, in __pyroCreateConnection
connect_and_handshake(conn)
File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 549, in connect_and_handshake
raise ce
Pyro4.errors.CommunicationError: cannot connect to ('JAKOB-PC', 9090): [Errno -2] Name or service not known
My PC has its firewall disabled, so there shouldn t be any problem with that. My local ip is 192.168.1.5.
I am using a headless Raspberry and write code on it with puTTY and VNC.
I have googled this error but couldn t find any answers. Any help would be appreciated.
I did this
#
# Server.py
#
from __future__ import print_function
import Pyro4
#Pyro4.expose
#Pyro4.behavior(instance_mode="single")
class Messenger(object):
# This is a constructor
def __init__(self):
pass
# This method will be called on the server
def send_message(self, name, message):
print("[{0}] {1}".format(name, message))
def main():
Pyro4.Daemon.serveSimple(
{
Messenger: "example.messenger"
},
ns=True)
if __name__ == "__main__":
main()
#
# Client.py
#
# This is the code that visits the warehouse.
import sys
import Pyro4
import Pyro4.util
sys.excepthook = Pyro4.util.excepthook
messenger = Pyro4.Proxy("PYRONAME:example.messenger#192.168.1.5")
messenger.send_message("Tim", "Hello!")
Then ran
python -m Pyro4.naming -n 192.168.1.5
python Server.py
python Client.py
In short I couldn't solve the problem with Pyro and (almost) no one helped so I decided to use 'websockets' instead.
You can read the documentation here but I'll explain it here anyway.
First of all you need two devices with network connection. You also have to run python 3.6.1 on both of them. After that you also need to install websockets if you don't have them already with pip install websockets or as I had to do it with pip3 install websockets.
Code below runs on the server and handles messages you send to it from client. Function 'hello' is a simple example of processing request and sending back a response. 'request' is the data server receives, that data must be bytes, string on iterable. Response is made by converting request to integer, squaring it and converting it back to string. This response is then sent back to client.
'start_server' defines the server, function that will define its behavior(hello), ip address on witch the server is running on(192.168.1.117) and port on witch it will receive requests(8765).
!/usr/bin/env python
import asyncio
import websockets
print("Running...")
async def hello(websocket, path):
request = await websocket.recv()
print("Request: " + request)
response = str(int(request)*int(request))
await websocket.send(response)
print("Response:" + response)
start_server = websockets.serve(hello, "192.168.1.117", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Next bit is code on the client. 'uri' is ip and port of the server. Function 'tellServ' asks you to input some data('tell' variable) and sends it to the server. After that it waits for reply and once it gets it it prints it out. In this case if I would input number "6" server would reply with "36". Function loop is in a while loop so I can send multiple numbers without having to restart the script.
#!/usr/bin/env python
import asyncio
import websockets
uri = "ws://192.168.1.117:8765"
async def tellServ():
async with websockets.connect(uri) as websocket:
tell = input("Podatek ki ga posles: ")
await websocket.send(tell)
reply = await websocket.recv()
print("Odgovor:")
print(reply)
while 1:
asyncio.get_event_loop().run_until_complete(tellServ())

How to solve the address issue if I restart an external service inside python with flask?

I am using flask to build a python web service, for example, I set the flask port as 8080 like this:
#app.route('/data', methods=['POST'])
def data_construct():
os.system('sh restart.sh')
if __name__ == '__main__':
app.debug = True
app.run(host='0.0.0.0', port=8080)
and the restart.sh is used for restarting an external service, but after I send a HTTP POST request to /data, the restart is successfully completed, but after a while, I get an error:
Traceback (most recent call last):
File "hello.py", line 87, in <module>
app.run(host='0.0.0.0', port=8080)
File "/home/work/.jumbo/lib/python2.7/site-packages/flask/app.py", line 739, in run
run_simple(host, port, self, **options)
File "/home/work/.jumbo/lib/python2.7/site-packages/werkzeug/serving.py", line 613, in run_simple
test_socket.bind((hostname, port))
File "/home/work/.jumbo/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use
the 'restart.sh' is like this (storage is a C++-complied program):
killall storage
nohup ./storage &
and I find the external service is starting using the port 8080 which it is not supposed to do (its original port is still in use), how to solve this problem?

How to handle multiple publishers on same port in zmq?

This question has been asked before, here. I have the exact same problem. I want to publish from a bunch of different processes, and use the same port every time.
I tried the solution presented in the answer, but this did not work for me. I get the error
File "/usr/local/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/local/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "/home/akay/afk/multi.py", line 18, in to_zmq
socket.connect("tcp://*:%s" % port)
File "zmq/backend/cython/socket.pyx", line 478, in zmq.backend.cython.socket.Socket.connect (zmq/backend/cython/socket.c:4308)
ZMQError: Invalid argument
My code is like this, essentially taken straight from the example in the zmq docs here and here:
# Socket to talk to server
port = '5556'
context = zmq.Context()
socket = context.socket(zmq.SUB)
print "Listening for stream...", m
socket.bind("tcp://localhost:%s" % port) #change connect to bind, as per answer above
socket.setsockopt(zmq.SUBSCRIBE, topicfilter)
I am using python 2.7, and the most recent version of zmq. Any idea what I might be doing wrong?
Well, the error is clear:
[...]
socket.connect("tcp://*:%s" % port)
[...]
ZMQError: Invalid argument
You can't connect to *, you must specify an IP address (the server IP address). If both the client and the server run on a single machine, try with localhost or 127.0.0.1.

Why is this MQTT client example failing?

I am trying out MQTT for the first time using Python and the mosquitto library. My client program is below. I'm trying to use the public demo MQTT server at http://www.mqtt-dashboard.com/subscribe. However the client code is failing, see error below. Any ideas on what's going on?
#!/usr/bin/env python
import mosquitto
client = mosquitto.Mosquitto("fredtest", clean_session=True)
client.connect("broker.mqttdashboard.com", 1883)
client.publish("fred.test", "hello world", 1)
client.loop_forever()
Error message:
C:\tmp>python mqttclient.py
Traceback (most recent call last):
File "mqttclient.py", line 6, in
client.connect("broker.mqttdashboard.com", 1883)
File "build\bdist.win-amd64\egg\mosquitto.py", line 582, in connect
File "build\bdist.win-amd64\egg\mosquitto.py", line 657, in reconnect
File "c:\python27\lib\socket.py", line 571, in create_connection
raise err
socket.error: [Errno 10060] A connection attempt failed because the connected pa
rty did not properly respond after a period of time, or established connection f
ailed because connected host has failed to respond
I'm not currently able to connect any client to broker.mqttdashboard.com:1883 - so this probably isn't an issue with your code.
To sanity check, have you tried connected to another broker, such as iot.eclipse.org:1883 ?

Connecting to Gmail from Python

I've been trying to connect to my Gmail account using python. imap is enabled.
import imaplib
imap_server = imaplib.IMAP4_SSL("imap.gmail.com",993)
# also tried imap_server = imaplib.IMAP4_SSL("imap.gmail.com"), doesnt work.
Traceback is :
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
imap_server = imaplib.IMAP4_SSL("imap.gmail.com",993)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 1202, in __init__
IMAP4.__init__(self, host, port)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 172, in __init__
self.open(host, port)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 1217, in open
IMAP4.open(self, host, port)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 248, in open
self.sock = self._create_socket()
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 1205, in _create_socket
sock = IMAP4._create_socket(self)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/imaplib.py", line 238, in _create_socket
return socket.create_connection((self.host, self.port))
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socket.py", line 435, in create_connection
raise err
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socket.py", line 426, in create_connection
sock.connect(sa)
OSError: [Errno 65] No route to host
What OSError: [Errno 65] No route to host means is what it say: you can't get to that machine from your machine.
You can test that from outside of Python by opening up a terminal/DOS prompt and typing this:
ping imap.gmail.com
It's possible that this is actually a name lookup error, and you're somehow getting a bad address for imap.gmail.com. So, just to be sure, check by IP address too:
ping 74.125.129.108
ping 74.125.129.109
If ping works, you can check whether your router is for some reason just blocking TCP access to the host, e.g., with:
telnet imap.gmail.com
If it's working, this should either hang for a long time, or give you a connection-refused error; if it gives you a no-route-to-host error, it's the same problem you're seeing.
It's also possible that your router is specifically blocking port 993. You can test this too:
telnet imap.gmail.com 993
If it doesn't come back with something like "Connected to gmail-imap.l.google.com", same problem here too.
At any rate, once you've verified that this is a system or network configuration problem, not a programming problem, go ask for help with your system on the appropriate site.

Categories