希望在 Python 中模拟 socat 的功能

Posted

技术标签:

【中文标题】希望在 Python 中模拟 socat 的功能【英文标题】:Looking to emulate the functionality of socat in Python 【发布时间】:2017-02-12 18:57:42 【问题描述】:

我需要使用 python 将字符串发送到本地主机上的特定端口。

我可以通过在命令行上使用 socat 来实现这一点,如下所示:

cat <text file containing string to send> | socat stdin tcp-connect:127.0.0.1:55559

我不想将 socat 命令作为子命令运行,所以我想知道如何使用 python 模块使其工作。

我尝试使用套接字失败了。下面是我使用的一个脚本,它没有达到预期的效果。

    import socket
    HOST, PORT = "127.0.0.1", 55559
    jsonString = '"name":"VideoStreamStatus","parameters":"name":"video_0_0"'

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        # Connect to server and send data
        print "Attempting connection"
        sock.connect((HOST, PORT))
        print "Sending json string"
        sock.sendall(jsonString)
        print "String sent"

    finally:
        sock.close()

    print "Sent:     ".format(jsonString)

python 脚本执行时没有任何错误,但对接收 socat 数据的进程没有任何影响。 Python 脚本输出如下:

    Attempting connection
    Sending json string
    Sent:     "name":"VideoStreamStatus","parameters":"name":"video_0_0"

我在套接字脚本中做错了什么还是我可以在 Python 中使用不同的方法?我会很感激任何建议。谢谢。

编辑:我尝试向其发送字符串的服务器是 C++ 程序的一部分,该程序使用 boost asio 接受器来侦听特定地址和端口上的 tcp 连接。

【问题讨论】:

您的代码非常适合我。我的服务器 nc -l 55559 在其标准输出上显示 json 字符串。请描述您正在使用的服务器,以及是什么让您认为“对接收 socat 数据的进程没有任何影响”。 @Robᵩ 我尝试向其发送字符串的服务器是 C++ 程序的一部分,该程序使用 boost asio 接受器侦听特定地址和端口上的 tcp 连接。 【参考方案1】:

原来是一件非常简单的事情。我使用 socat 发送的字符串(服务器正在成功接收和处理)在它的末尾有一个换行符。我通过 python 套接字发送的字符串没有新行。在 python 脚本的末尾添加新行后,服务器按预期接收字符串。

在运行 python 服务器脚本侦听不同端口并使用这两种方法发送字符串后,我才意识到一个后有一个换行符,而不是另一个后一个换行符。

【讨论】:

【参考方案2】:

你永远不能在写入套接字后立即关闭套接字:关闭可能会吞下仍未发送的数据。

正确的工作流程是所谓的graceful shutdown:

想要关闭连接的部分在套接字上使用shutdown-write 并继续读取 另一部分检测到从套接字读取的 0 字节,这被视为文件结尾。它关闭它的套接字 发起者检测到一个 0 字节读取并且可以安全地关闭套接字

所以finally 部分变为:

finally:
  try:
    sock.shutdown(socket.SHUT_WR)
    while True:
        dummy = sock.recv(1024)
        if len(dummy) == 0: break
  finally:
    sock.close()

【讨论】:

感谢您的建议,但进行这些更改并没有改变结果,服务器似乎仍然没有收到任何消息。【参考方案3】:

根据the socat man page,

当一个通道达到 EOF 时,另一个通道的写入部分被关闭。然后,socat 在终止前等待timeout 秒。默认值为 0.5 秒。

也许您需要将关闭时间推迟 0.5 秒,如下所示:

finally:
    #sock.close()
    sock.shutdown(socket.SHUT_WR)
    time.sleep(0.5)
    sock.close()

或者,也许您需要吸收服务器的关闭消息,如下所示:

finally:
    #sock.close()
    sock.shutdown(socket.SHUT_WR)
    sock.recv(999999)
    sock.close()

【讨论】:

对结果没有任何影响。还是谢谢。

以上是关于希望在 Python 中模拟 socat 的功能的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Python 中模拟后台控制台活动?

Python 运行守护程序子进程并读取标准输出

haproxy调度算法详解一

将按钮绑定到VPython 7功能

python实现简单随机模拟——抛呀抛硬币

sh 使用bash和[nc | socat]的http请求示例(在unix域套接字中)