希望在 Python 中模拟 socat 的功能

Looking to emulate the functionality of socat in Python

我需要使用 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 中使用其他方法吗?我将不胜感激任何建议。谢谢

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

根据the socat man page

When one channel has reached EOF, the write part of the other channel is shut down. Then, socat waits timeout seconds before terminating. Default is 0.5 seconds.

也许您需要将关闭延迟 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()

切勿在写入套接字后立即关闭套接字:关闭操作可能会吞噬尚未发送的数据。

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

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

因此 finally 部分变为:

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

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

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