【问题标题】:Alternative to TCP/IP for local program-to-program data streaming?本地程序到程序数据流的 TCP/IP 替代方案?
【发布时间】:2011-12-30 17:41:23
【问题描述】:

我有一个 GNU C++ 程序和一个 python 脚本,它们需要非常频繁地相互传递字符串(每分钟约 70-80 条消息)。它们将在 CentOS 中彼此本地运行(托管在同一环境中)。感觉虽然 TCP/IP 可以并且将会完成工作,但我还有什么其他选择?

请记住,我不能将我的 C++ 程序变成 SO 并使用 ctypes 将其集成到我的 python 脚本中,我的 C++ 程序必须以 32 位编译,而我的 python 脚本必须是 64 位。

【问题讨论】:

  • 是什么引起了您的关注?您对使用 TCP/IP 不满意有什么原因吗?在不知道 TCP 遇到什么问题的情况下,很难有效地推荐替代方案。
  • 普遍的好奇心和对 TCP/IP 感觉的唠叨感觉……没有必要。你真的不需要协议提供的整个流量控制/交付保证/握手。
  • 每分钟 70-80 条消息是如此之低,以至于花任何时间优化 IPC 机制都是浪费时间。无论您能以最快的速度编写代码,都是最佳选择。我不知道你的 C++ 程序是什么,但我会认真考虑你是否应该只用 python 编写整个东西并完全避免消息传递。

标签: c++ python linux networking gcc


【解决方案1】:

命名管道是标准方法。在 Python 中:

import os

os.mkfifo('/some/path')

# Reading process

with open('/some/path') as pipe:
    for line in pipe:
        # Do what you need

# Writing process

with open('/some/path', 'w') as pipe:
    while True: # Whatever looping process you have
        pipe.write('<data>' + '\n')

请注意,在现代系统上,70-80 条消息/分钟并不是那么高,TCP 仍然是一个可行的选择。还要注意没有一个字符串大于管道缓冲区大小(通常为 64K)。

根据 cmets 中的建议,我还添加了一个 UNIX 域套接字的示例,如果您需要双向通信,它会更有用。

# Server Side

import socket

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind("/some/path")

sock.listen(1)
conn, addr = sock.accept()

while True:
    data = conn.recv(1024)
    if not data:
        break

    # Let's echo it back as an example
    conn.send(data)

conn.close()

# Client Side

import socket

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/some/path")

while True: # Your sending loop
    # In this case we send hello world, and print what we get back.
    sock.send('Hello, world')
    data = sock.recv(1024)

    print data

sock.close()

【讨论】:

  • 你知道它在 c++ 端的样子吗?我不确定这是什么库。
  • 命名管道是单向的。 UNIX 域套接字是双向的,因此可能更适合“交换消息”。
  • @user1040625 它被视为文件,因此您可以使用标准的 fopen / fread / fwrite 调用。 mkfifo 在 sys/stat.h 中可用。
【解决方案2】:

http://tldp.org/LDP/tlk/ipc/ipc.html

  • 管道
  • 命名管道
  • TCP 套接字
  • UNIX 域套接字
  • 消息队列
  • 共享内存

到目前为止,我更喜欢 TCP 套接字。

  1. 您已经为它们编写了支持,
  2. 它们在机器间和机器内都能很好地工作。
  3. 有很多很棒的工具可以调试通信通道。
  4. 有图书馆可以帮助他们使用。

【讨论】:

    【解决方案3】:

    如果您已经拥有 TCP 或 UDP 服务器,最简单的方法可能是切换到 UNIX 域套接字。

    它们以“流”和“数据报”模式出现,就像 TCP/UDP 套接字一样,并且它们始终是本地的,因为它们使用文件系统命名空间(而不是像 TCP/UDP 这样的端口号)。

    【讨论】:

    • +1,我很喜欢这种方法,因为它可以让您在未来通过最少的代码重写轻松地将两个进程分离到不同的盒子上。
    • 但是使用 UNIX 域套接字比使用 TCP/UDP 套接字有什么优势呢?
    • 在 tcp/ip 上使用域套接字的优缺点是什么?
    • 使用 TCP 和 UDP 会占用一个端口。当然,您只能绑定到 localhost,但它仍然是一个端口。如果有人配置错误并让它监听所有接口,它可能会从其他地方受到攻击。然后是 IPv4/IPv6 切换开始发生。四处头痛。使用 UNIX 域套接字,您可以在文件系统中具有写访问权限的任何位置创建更多套接字。如果(以及何时!)需要,您可以随时重写它以使用 TCP/UDP。
    • @Rob:您可以使用 UNIX 权限来控制对 UNIX 域套接字的访问;您可以通过 UNIX 域套接字传递文件描述符;您可以传递经过内核验证的 PID、UID 和 GID 凭据;并且您可以将SOCK_SEQPACKET 与 UNIX 域套接字一起使用。
    【解决方案4】:

    也许你可以使用命名管道?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      • 1970-01-01
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多