0

我正在尝试使用套接字技术从在 pc 上运行的 C# 程序(服务器)将两个整数发送到 python 客户端脚本(在 Linux 机器上运行)。到目前为止,我能够发送字符串。

服务器:

TcpListener listener = new TcpListener(IPAddress.Any, 12345);
Invoke(new PrintMsg(printMsg), new object[] { "Trying to connect" });
listener.Start();

for(; ; ;)
{
   TcpClient client = null;

   try
   {
      client = listener.AcceptTcpClient();
      netStream = client.GetStream();
      Invoke(new PrintMsg(printMsg), new object[] { "Found client" });


      //send command to client
      ASCIIEncoding encoder = new ASCIIEncoding();
      byte[] buffer = encoder.GetBytes("Hello client");
      netStream.Write(buffer, 0, buffer.Length);
      netStream.Flush();

   }

   catch (Exception ex)
   {
      Invoke(new PrintMsg(printMsg), new object[] { ex.ToString() });
   }
}

客户端代码是:

while True:
    msg = s.recv(1024)
    print 'SERVER:', msg

所以我想将一个整数“放入”缓冲区数组,然后将其发送到 python 脚本。可能吗?我究竟做错了什么?

4

2 回答 2

2

很难从您的客户端代码中分辨出您用于建立 TCP 连接的客户端库类型。

为什么不使用一些支持 C# 和 Python 的消息队列实现,例如 ZeroMQ?如果您需要更复杂的数据结构传递,您还可以考虑使用一些内存键值存储解决方案来实现队列,例如 Redis。优点是消息队列服务器/客户端实现设计良好,您只需编写一两行代码即可在业务逻辑中发送/接收。

于 2013-02-27T21:06:13.420 回答
2

在解决“我如何发送整数?”的问题之前,您需要解决一个更大的问题:“我如何发送消息?”

在 TCP 中,当您send在一侧调用时,即使它一次发送整个缓冲区(不能保证),另一端可能会在多个单独的recv调用中获取数据,而不是一次全部调用。send更糟糕的是,它可能会send在单个recv.

您可以使用更高级别的协议(例如 ZeroMQ,甚至 HTTP)来为您处理这些问题。但是如果你只想使用原始 TCP,你必须自己处理它。

一个明显的解决方案是像换行符(或 NUL 字节等)这样的分隔符——但当然你需要某种方式在消息中间转义换行符。另一种可能性是使用某种描述消息其余部分的标头,例如netstring。或者,您可以使用像 JSON 这样的自定界消息类型。

许多非常简单的处理分隔符问题的方法会自动处理发送整数。JSON 将数字作为一种类型。或者您可以将整数作为字符串发送到网络字符串或换行符分隔的字符串上。

如果您真的想以某种“二进制”方式对数字进行编码,则必须选择一个表示,并编写代码以在每一侧与该表示进行转换。例如,如果您想将事物限制为 32 位有符号整数,并以大端 C 整数格式发送它们,那么 Python 代码就是buf = struct.pack('!I', number)and number = struct.unpack('!I', buf).

但是您应该考虑是否需要二进制格式。作为人类,显然更难阅读和调试。它也更容易出错(例如,通过忘记字节顺序或字长)。并且简单的方法是有限的(例如,上述!I格式对于大于约 20 亿的数字将失败)。它甚至不一定更紧凑。通常,您会发送大量小数字,它们需要 2-3 个字节作为带有换行符的字符串,但 4 个字节是二进制形式。

这是基于行的数字阅读器的简单 Python 实现:

def read_numbers_off_socket(s):
    buf = ''
    while True:
        newbuf = s.recv(4096)
        if not newbuf:
            yield int(buf)
            break
        buf += newbuf
        lines = buf.split('\n')
        for line in lines[:-1]:
            yield int(line)

但是你可以更简单地做到这一点s.makefile

def read_numbers_off_socket(s):
    with s.makefile() as f:
        for line in f:
            yield int(line)
于 2013-02-27T21:13:27.297 回答