C#中的Struct.Pack等效

时间:2013-10-12 17:22:59

标签: c# python

我正在构建一个连接到渲染应用程序并且失败的C#客户端! 我通过剖析一个对这一行起作用的python客户端来缩小问题范围:

   def Startclient_Click(self, sender, e):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((host, int(port)))
            message =  b'message "Render"'
            msg = struct.pack('<l',len(message))+struct.pack('<l',0)+message
            #print(msg)            
            s.sendall(msg)
            data = s.recv(1024)     

            data.decode("utf-8")        
            self.datatxt.Text ="data: " +str(data)
            s.close()

            return
        except:
            self.datatxt.Text ="No Server Connection"
            return

C#中的等价物是什么? 据我所知,消息需要8个字节

对于这个愚蠢的问题感到抱歉,但我已经好几天了,而且我失去了生存的意愿 感谢

1 个答案:

答案 0 :(得分:3)

struct.pack采用一种格式,后跟一系列将根据格式打包的值。在你的问题中,你打电话:

struct.pack('<l', len(message))+struct.pack('<l',0)+message

这就是说“将这条消息的长度打包成一个小尾数,然后将零封装成一个小尾数,然后附加剩下的消息”。

当你在C#中遇到这种问题时,我们很遗憾没有struct.pack的直接端口。您最接近的等价物是使用BitConverter进行一次性转换,例如:

BitConverter.GetBytes((long)message.length) + BitConverter.GetBytes(0l) + message

或使用BinaryWriter加入MemoryStream。这带来了另一个问题,即您无法使用这些工具控制字节序。他们揭露了“IsLittleEndian”,所以你知道他们是如何行动但你不能改变它。

然而,Jon Skeet就是这个案例 - 他的MiscUtils库包含一个可以使用的LittleEndianBitConverter(MiscUtil.Conversion.LittleEndianBitConverter),或者你应该使用EndianBinaryWriter写入Writer / MemoryStream路径。所以把它们放在一起,引用MiscUtil库并使用类似的东西:

var bytes = new List<byte[]>(new[]
    {
        LittleEndianBitConverter.GetBytes(message.LongLength), 
        LittleEndianBitConverter.GetBytes(0l), 
        message
    });

var msg = new byte[bytes.Sum(barray => barray.LongLength)];
int offset = 0;
foreach (var bArray in bytes)
{
    System.Buffer.BlockCopy(bArray, 0, msg, offset, bArray.Length);
    offset = bArray.Length;
}

代码未经测试但应该给你一个合理的起点。假设您的消息已经是一个字节数组,而msg是您想要返回的数组。我们使用System.Buffer.BlockCopy,因为它是原始类型最有效的复制方法。

*编辑 *

我在问题中采用了示例,并在IDEOne及其Python code中为equivalent in C#模拟了一个快速脚本。这里的问题是Struct.Pack('<l', 0)调用会忽略该字节,并且不会将其添加到输出中,这可能会使您绊倒。这导致输出太长8个字节。

这些脚本应该指向正确的方向。如果您仍然遇到问题,可以发布您尝试过的代码。

供参考,Python中已完成的代码:

import struct
message =  b'message "Render"'
msg = struct.pack('<l',len(message)) + struct.pack('<l',0) + message
print(":".join("{0:x}".format(ord(c)) for c in msg))

在C#中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MiscUtil.Conversion;

public class Test
{
    public static void Main()
    {
        var message = Encoding.ASCII.GetBytes("message \"Render\"");

            var lenc = new LittleEndianBitConverter();

            var bytes = new List<byte[]>(new[]
            {
                lenc.GetBytes(message.LongLength),
                message
            });

            var msg = new byte[bytes.Sum(barray => barray.LongLength)];
            int offset = 0;
            foreach (var bArray in bytes)
            {
                Buffer.BlockCopy(bArray, 0, msg, offset, bArray.Length);
                offset = bArray.Length;
            }

            Console.WriteLine(BitConverter.ToString(msg).Replace("-", ":"));
    }
}