Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Non-blocking socket or Asynchronos I/O

I am new to Python and currently have to write a python socket to be run as a script that communicates with a device over TCP/IP (a weather station).
The device acts as the Server Side (listening over IP:PORT, accepting connection, receiving request, transferring data).
I only need to send one message, receive the answer and then peacefully and nicely shutdown and close the socket.

try:
    comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    sys.stderr.write("[ERROR] %s\n" % msg[1])
    sys.exit(1)

try:
   comSocket.connect((''))
except socket.error, msg:
   sys.stderr.write("[ERROR] %s\n" % msg[1])
   sys.exit(2)

comSocket.send('\r')
comSocket.recv(128)
comSocket.send('\r')
comSocket.recv(128)
comSocket.send('\r\r')
comSocket.recv(128)

comSocket.send('1I\r\r3I\r\r4I\r\r13I\r\r5I\r\r8I\r\r7I\r\r9I\r\r')

rawData = comSocket.recv(512)

comSocket.shutdown(1)
comSocket.close()

The problem I'm having is:
The communication channel is unreliable, the device is slow. So, sometimes the device response with message of length 0 (just an ACK), the my code will freeze and wait for response forever.
This piece of code contains the portion that involves SOCKET, the whole code will be run under CRON so freezing is not a desirable behavior.

My question is:
What would be the best way in Python to handle that behavior, so that the code doesn't freeze and wait forever but will attempt to move on to the next send (or such).

like image 399
Tu Hoang Avatar asked Jun 16 '11 15:06

Tu Hoang


2 Answers

Try, before receiving, putting a timeout on the socket:

comSocket.settimeout(5.0)
try:
    rawData = comSocket.recv(512)
except socket.timeout:
    print "No response from server"
like image 76
Russell Borogove Avatar answered Oct 02 '22 00:10

Russell Borogove


You can try a timeout approach, like Russel code or you can use a non-blocking socket, as shown in the code below. It will never block at socket.recv and you can use it inside a loop to retry as many times you want. This way your program will not hang at timeout. This way, you can test if data is available and if not, you can do other things and try again later.

socket.setblocking(0)
while (retry_condition):
    try:
        data = socket.recv(512)
    except socket.error:
        '''no data yet..'''
like image 38
Felipe Cruz Avatar answered Oct 01 '22 22:10

Felipe Cruz