我正在构建一个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字节前的消息。
struct.pack采用一种格式,后跟一系列值,这些值将根据格式进行打包。在你的问题中,你称之为:
struct.pack('<l', len(message))+struct.pack('<l',0)+message
也就是说“将此消息的长度打包为一个小尾端长度,然后将零打包为一个小尾端长度,然后再将我的消息的其余部分追加”。
当您在C#中处理此类问题时,不幸的是,我们没有struct.pack.的直接端口。您最接近的等价物将是使用BitConzer进行一次性转换,例如:
BitConverter.GetBytes((long)message.length) + BitConverter.GetBytes(0l) + message
或者在MemoryStream中使用二进制编写器。然而,这带来了另一个问题,即您无法使用这些工具来控制endpoint。他们揭露了“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.缓冲区。BlockCopy是对基元类型最有效的复制方法。
*编辑*
我以问题中的例子为例,在IDEOne中为Python代码及其在C#中的等价物模拟了一个快速脚本。这里的关键是结构。包
这些脚本应该为你指明正确的方向。如果你仍然有问题,你能发布你尝试过的代码吗?
作为参考,在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("-", ":"));
}
}