【问题标题】:Looking to emulate the functionality of socat in Python希望在 Python 中模拟 socat 的功能
【发布时间】: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 连接。

标签: python socketserver socat


【解决方案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()
    

    【讨论】:

    • 对结果没有任何影响。还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 2010-09-14
    • 2012-10-11
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    相关资源
    最近更新 更多