Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Socket: Handling TCP connections over a cell network

I am doing some socket programming in python in which I develop a client TCP/IP socket to communicate with a slow embedded device. So sometimes, when the response is supposed to be only one package, it is broken in to two packages. My current solution to that is to sleep() the python program, waiting to make sure that all the data I need already arrived.

comSocket.send('\r')

sleep(1)

comSocket.send('\r')

comSocket.recv(128)

comSocket.send('\r\r')

comSocket.recv(256)



#sending I commands for data

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

sleep(2)

#receiving data

rawData = comSocket.recv(512)

sleep(1.5)

I am wondering whether there is a better way to handle this situation?

like image 340
Tu Hoang Avatar asked Mar 08 '26 06:03

Tu Hoang


1 Answers

If it is a single device, you should use a solution that handles the low-level socket interactions for you... python has several like pexpect, exscript, or paramiko (ssh only)... if it is multiple devices and you need asynchronous communication, use @zeekay's answer (although async programming, particularly with twisted, is unpleasant if you're not already familiar with it).

I answered a question with the way you telnet and send a list of commands to a single device here...

Catching a dying process in pexpect

The answer above makes the code efficient, but is more challenging for a beginner to understand... the following code is simpler, it makes a telnet connection on TCP/23, waits for *, sends a command, and puts the response to the command in mydata1...

import pexpect as px
import sys

def send_this(child, retcode, COMMAND):
    if retcode == 2:
        child.sendline(COMMAND)
    else:
        raise RuntimeError, "Could not complete login, due to socket error"

def expect_this(child, EXPR, timeout = 10):
    return child.expect([px.TIMEOUT, px.EOF, EXPR], timeout = timeout)

HOST = '192.168.49.49'
CMD1 = '1I'
PROMPT = '\*'     #Note: you might not need the backslash
TIMEOUT = 10

child = px.spawn('telnet %s' % HOST)
retcode = expect_this(child, PROMPT)
send_this(child, retcode, CMD1)
retcode = expect_this(child, PROMPT)
mydata1 = child.before    # mydata has the output from CMD1

Regardless of the solution, the most important thing is tweaking your timeouts so you don't have to concern yourself with the long cell-network delays (which are sometimes over 5 seconds in my experience).

The other nasty dynamic in cellular communication is that many consumer devices routinely change their IP address when they are moving (due to their reliance on dhcp)... there isn't much TCP can do if this happens... if you don't have a static address the connection will drop when the device pulls a new ip address.

like image 189
Mike Pennington Avatar answered Mar 10 '26 20:03

Mike Pennington



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!