【问题标题】:Python: Socket: Handling TCP connections over a cell networkPython:套接字:通过蜂窝网络处理 TCP 连接
【发布时间】:2011-09-03 15:00:10
【问题描述】:

我正在 python 中进行一些套接字编程,在其中我开发了一个客户端 TCP/IP 套接字来与速度较慢的嵌入式设备进行通信。所以有时,当响应应该只有一个包时,它被分成两个包。我目前的解决方案是sleep() python 程序,等待确保我需要的所有数据都已经到达。

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)

我想知道是否有更好的方法来处理这种情况?

【问题讨论】:

  • 您能具体谈谈沟通渠道吗?这是 IP 网络、串行总线还是??
  • @Mike Pennington:这是基于 IP 网络的 TCP/IP 套接字。

标签: python sockets tcp pexpect


【解决方案1】:

如果是单个设备,您应该使用为您处理低级socket 交互的解决方案... python 有几个类似pexpect、exscript 或paramiko (ssh only)...如果它是多个设备,您需要异步通信,请使用@zeekay 的答案(尽管异步编程,特别是扭曲的,如果您还不熟悉它,会令人不快)。

我用你 telnet 的方式回答了一个问题,并将命令列表发送到这里的单个设备...

Catching a dying process in pexpect

上面的答案使代码高效,但对于初学者来说更难理解……下面的代码更简单,它在 TCP/23 上建立一个 telnet 连接,等待*,发送一个命令,然后将对命令的响应放在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

不管解决方案如何,最重要的是调整超时,这样您就不必担心长时间的蜂窝网络延迟(根据我的经验,有时延迟超过 5 秒)。

蜂窝通信中的另一个令人讨厌的动态是,许多消费者设备在移动时定期更改其 IP 地址(由于它们依赖 dhcp)...... TCP 无能为力如果发生这种情况...如果您没有静态地址,则当设备提取新的 IP 地址时连接将断开。

【讨论】:

  • 设备有静态IP。我现在正在阅读pexpect,它似乎很难消化,因为我以前从未用 python 编写过代码。这实际上是我第一次 :)
  • @Tanner,如果这是您第一次尝试在 python 中编码,那么使用 socket 模块处理 TCP 套接字并不会更令人愉快...我将为您发布一个简单的脚本...你使用的是 windows、osx 还是 linux?
  • @Mike Pennington:我使用的是 Linux,python 2.7.2
  • @Mike Pennington:我正在阅读你的剧本。对于我的设备来说,它要简单得多:没有涉及身份验证,我只需要建立连接,发送 3 条不同的消息,接收相应的响应,由于延迟时间长且波动,我不得不sleep()我的代码。我正在寻找一种更好的方法来处理等待替换sleep()。
  • @Tanner,没问题...我编辑了我认为您需要的内容...如果这不起作用,请告诉我...如果没有,您有什么问题。 ..注意,如果您需要查看此脚本的终端日志,您可以插入child.logfile = sys.stdout...
【解决方案2】:

使用像twisted 或zeromq 这样的网络库。

【讨论】:

    【解决方案3】:

    您必须在循环中recv,并且必须检查协议解析器是否已收到所有消息..

    condition = True
    while condition:
        rawData += sock.recv(512)
        # parse rawData to check if message is complete and if so you can set condition = False to break the loop
        if parser.is_complete(rawData):
            condition = False
    

    【讨论】:

    • 要为解析器导入的library 或module 是什么?
    • 那是一个说明性代码.. 你的设备有协议吗?可能你将不得不实施或寻找一种实施......
    猜你喜欢
    • 1970-01-01
    • 2020-12-02
    • 2014-08-31
    • 1970-01-01
    • 2019-10-07
    • 2012-03-28
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    相关资源
    最近更新 更多