首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Struct.Pack等价于C#?

Struct.Pack等价于C#?
EN

Stack Overflow用户
提问于 2013-10-12 17:22:59
回答 1查看 6.9K关注 0票数 6

我正在构建一个连接到呈现应用程序并令人沮丧地失败的C#客户端!我通过剖析运行于这一行的python客户机来缩小问题范围:

代码语言:javascript
复制
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字节。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-13 10:47:01

struct.pack采用一种格式,然后是一系列将根据格式打包的值。在你提出的问题中:

代码语言:javascript
复制
struct.pack('<l', len(message))+struct.pack('<l',0)+message

它的意思是“将这个消息的长度打包为一个小端长,后面是一个零包,后面是一个小端长,后面是我的消息的其余部分”。

当您在C#中处理这类问题时,不幸的是,我们没有直接的struct.pack端口。您最接近的等价物是使用BitConverter进行一次性转换,例如:

代码语言:javascript
复制
BitConverter.GetBytes((long)message.length) + BitConverter.GetBytes(0l) + message

或者将BinaryWriter使用到MemoryStream中。然而,这带来了另一个问题,即您无法使用这些工具控制endian-ness。他们暴露了"IsLittleEndian“,所以你知道他们的行为,但你不能改变它。

但是,Jon是这样的--他的MiscUtils库包含一个您可以使用的LittleEndianBitConverter LittleEndianBitConverter,或者如果您选择Writer/MemoryStream路由的话,它包含一个EndianBinaryWriter。因此,将它们放在一起,引用MiscUtil库并使用如下内容:

代码语言:javascript
复制
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代码及其等效于C#模拟了一个快速脚本。这里的问题是,Struct.Pack('<l', 0)调用忽略了字节,并且没有将它添加到输出中,这可能是导致您崩溃的原因。这导致输出长了8个字节。

这些脚本应该为您指明正确的方向。如果你仍然有问题,你可以张贴你尝试过的代码。

作为参考,Python中完成的代码如下:

代码语言:javascript
复制
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#中:

代码语言:javascript
复制
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("-", ":"));
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19337056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档