how can I catch sendMessage error ? There is no exception propagation. When the server is down (half-open connection) I want catch the error in my client code. If the server running the websocket daemon crashes, reboots, loses network connectivity closeConnection/ConnectionLost/ConnectionFailed callbacks does not work.
from autobahn.websocket import WebSocketClientProtocol
class ClientProtocol(WebSocketClientProtocol):
def onOpen(self):
def heartbeat():
self.sendMessage("HB")
self.factory.reactor.callLater(1, heartbeat)
# I want to catch a socket error
try:
heartbeat()
except Exception as e:
print e
Maybe there are better solutions than this. Ping Pong ? Simply I cannot find a way how my client can detect server crash/reboots then reconnect.
I am using autobahn 0.6.5
Yes, there is a better solution for fast detection of lost connections: WebSocket ping/pong. This is built into the WebSocket protocol.
AutobahnPython supports automatic WebSocket Ping/Pong, mostly for exact this scenario (fast connection loss detection and connection keep-alive).
You can activate this using these parameters:
autoPingInterval
autoPingTimeout
autoPingSize
which can be set for both servers and clients.
You will need a recent AutobahnPython version (0.9.4+ I think). Yours (0.6.5) does not have that feature.
Related
I'm working on a Python script with a client/server socket. After searching for alternate solutions, I'm not sure if my solution is correct or the best.
I have read these posts :
Python handling socket.error: [Errno 104] Connection reset by peer
Asyncio detecting disconnect hangs
Their solutions do not work for me, but I have the following .I'm not sure if that it's correct or clean.
try:
# See if client has disconnected.
try:
data = (await asyncio.wait_for(client_reader.readline(),timeout=0.01))
except ConnectionResetError, ConnectionAbortedError) as e:
break # Client disconnected
except TimeoutError:
pass # Client hasn't disconnect
If i don't use except for ConnectionResetError, I get an error because the data raises connectionReset when I kill the client.
Is it a good solution to detect an irregular client disconnection ?
ps : Thank you Prune for cleaned up wording and grammar.
As long as you are not interacting with the socket, you don't know if it's still connected or not. The proper way to handle disconnections is not to checks the state of the socket, but to verify if a read or write operation failed because of such error.
Usually, one is always at least awaiting for a read() on a socket, this is where one should look for disconnections. When the exception happens, the stream will be detected as closed and propagate the exception to any other task awaiting on an operation on this socket. It means that if you have concurrent operations on one stream, you must expect this exception to be raised anywhere, and handle it everywhere in your code.
About the exceptions caught: Checking for a ConnectionError is the best solution, it's a parent class of all exceptions related to a connection (ConnectionAbortedError, ConnectionResetError, etc).
I am using Python Tornado's websocket_connect function ( http://tornadokevinlee.readthedocs.org/en/latest/websocket.html ) to listen to a websocket feed.
Sometimes the websocket server will die, or disconnect the client (this is detectable ) and I need to figure out a way to clean up the old connection and reconnect the client. I could of course just restart the program but what is the proper way to do this through tornado?
There's nothing automatic for this. When it disconnects, just call websocket_connect() again.
I am creating a multicast listener using the Multicast Functionality provided by the Twisted Framework. So far, so good. However, I would like to detect if the interface is not already up when the application is launched (which throws a MulticastJoinError), and wait for it to be ready in order to subscribe to the group, or in the event that the network goes down unexpectedly, get some sort of notification so I can terminate the execution or handle it in any other way.
class Listener(DatagramProtocol):
def startProtocol(self):
try:
self.transport.joinGroup(MULTICAST_ADDR)
except MulticastJoinError:
#handle multicast error
reactor.listenMulticast(conf.PORT, Listener(), listenMultiple=True)
Thanks in advance!
I've been trying to figure out which form of connection i should use when using pika, I've got two alternatives as far as I understand.
Either the BlockingConnection or the SelectConnection, however I'm not really sure about the differences between these two (i.e. what is the BlockingConnection blocking? and more)
The documentation for pika says that SelectConnection is the preferred way to connect to rabbit since it provides "multiple event notification methods including select, epoll, kqueue and poll."
So I'm wondering what are the implications of these two different kinds of connections?
PS: I know I shouldn't put a tag in the title but in this case I think it does help to clarify the question.
The SelectConnection is useful if your application architecture can benefit from an asynchronous design, e.g. doing something else while the RabbitMQ IO completes (e.g. switch to some other IO etc) . This type of connection uses callbacks to indicate when functions return. For example you can declare callbacks for
on_connected, on_channel_open, on_exchange_declared, on_queue_declared etc.
...to perform operations when these events are triggered.
The benefit is especially good if your RabbitMQ server (or connection to that server) is slow or overloaded.
BlockingConnection on the hand is just that - it blocks until the called function returns. so it will block the execution thread until connected or channel_open or exchange_declared or queue_declared return for example. That said, its often simpler to program this sort of serialized logic than the async SelectConnection logic. For simple apps with responsive RabbitMQ servers these also work OK IMO.
I suppose you've read the Pika documentation already http://pika.readthedocs.io/en/stable/intro.html, if not, then this is absolutely vital information before you use Pika!
Cheers!
The Pika documentation is quite clear about the differences between the connection types. The main difference is that the pika.adapters.blocking_connection.BlockingConnection() adapter is used for non-asynchronous programming and that the pika.adapters.select_connection.SelectConnection() adapter is used for asynchronous programming.
If you don't know what the difference is between non-asynchronous/synchronous and asynchronous programming I suggest that you read this question or for the more deeper technical explanation this article.
Now let's dive into the different Pika adapters and see what they do, for the example purpose I imagine that we use Pika for setting up a client connection with RabbitMQ as AMQP message broker.
BlockingConnection()
In the following example, a connection is made to RabbitMQ listening to port 5672 on localhost using the username guest and password guest and virtual host '/'. Once connected, a channel is opened and a message is published to the test_exchange exchange using the test_routing_key routing key. The BasicProperties value passed in sets the message to delivery mode 1 (non-persisted) with a content-type of text/plain. Once the message is published, the connection is closed:
import pika
parameters = pika.URLParameters('amqp://guest:guest#localhost:5672/%2F')
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
channel.basic_publish('test_exchange',
'test_routing_key',
'message body value',
pika.BasicProperties(content_type='text/plain',
delivery_mode=1))
connection.close()
SelectConnection()
In contrast, using this connection adapter is more complicated and less pythonic, but when used with other asynchronous services it can have tremendous performance improvements. In the following code example, all of the same parameters and values are used as were used in the previous example:
import pika
# Step #3
def on_open(connection):
connection.channel(on_open_callback=on_channel_open)
# Step #4
def on_channel_open(channel):
channel.basic_publish('test_exchange',
'test_routing_key',
'message body value',
pika.BasicProperties(content_type='text/plain',
delivery_mode=1))
connection.close()
# Step #1: Connect to RabbitMQ
parameters = pika.URLParameters('amqp://guest:guest#localhost:5672/%2F')
connection = pika.SelectConnection(parameters=parameters,
on_open_callback=on_open)
try:
# Step #2 - Block on the IOLoop
connection.ioloop.start()
# Catch a Keyboard Interrupt to make sure that the connection is closed cleanly
except KeyboardInterrupt:
# Gracefully close the connection
connection.close()
# Start the IOLoop again so Pika can communicate, it will stop on its own when the connection is closed
connection.ioloop.start()
Conclusion
For those doing simple, non-asynchronous/synchronous programming, the BlockingConnection() adapter proves to be the easiest way to get up and running with Pika to publish messages. But if you are looking for a way to implement asynchronous message handling, the SelectConnection() handler is your better choice.
Happy coding!
I'm using python socket to connect to a server but sometimes I get this:
error: [Errno 10060] A connection attempt failed because the connected
party did not properly respond after a period of time, or established
connection failed because connected host has failed to respond
when I call the socket.connect method
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self._ipv4address, host_port))
try:
s.connect((dest_ip, dest_port))
except:
raise
Why am I seeing this error? And how do I solve the problem?
You don't need to bind the socket (unless the remote server has an expectation of incoming socket) - it is extremely rare that this would actually be a requirement to connect.
Instead of using sockets to open a website, use urllib2 or mechanize if you need to twiddle forms. They manage cookies, sessions, page state, etc.. Much easier.
Also, if you fail to to connect.. don't give up! Try again, some sites can be pokey to respond. Some may not respond for a while depending - handle it better. Instead of just raising the error, wrap your connection method with an exponential backoff decorator.