如何在传输后从字节重建结构[C#]

如何在传输后从字节重建结构[C#],c#,C#,我使用命名管道将数据从客户端(C++)传输到服务器(C#),客户端执行以下操作: // C++ Client sending message struct MESSAGE { char cCommand[8]; string sParameter; }; MESSAGE msg; strcpy(msg.cCommand, "COMMAND"); strcpy(msg.sParameter, "DO SOMETHING"); DWORD dwWrote = 0;

我使用命名管道将数据从客户端(C++)传输到服务器(C#),客户端执行以下操作:

// C++ Client sending message
struct MESSAGE
   {
   char    cCommand[8];
   string  sParameter;
   };

MESSAGE msg;
strcpy(msg.cCommand, "COMMAND");
strcpy(msg.sParameter, "DO SOMETHING");

DWORD dwWrote = 0;
WriteFile (hpipe, &msg, sizeof(msg), dwWrote, NULL);


// Then, at the receiving end the C# server recieve message:
IntPtr chRequest;
bool fSuccess = ReadFile(hPipeInst, chRequest, uSize, cbRead, OverlappedPtr);
if (fSuccess)
        byte[] temp = Encoding.ASCII.GetBytes(Marshal.PtrToStringAnsi(chRequest));
现在,在接收端,我需要将temp(byte[])转换回STRUCT或类似的东西,这样我就可以访问成员cCommand和sPatameter-但现在我不知道如何继续。。。实际上不需要是一个结构,我只需要提取数据本身

注意-STRUCT消息是我提出的,这意味着如果不同的格式有助于重建(例如添加sParameter的长度?),它可以更改,我只需要在单个块中传输命令和参数(如果可能)

要求很简单: -命令是一个固定长度的8个字符长的字符串,指示需要执行的操作 -参数是一个可变长度(除非这会导致问题)参数,取决于每个命令

例如: 命令=TRANS

参数=C:\FILE.txt C:\NewFolder\FILE.txt

(这只是为了说明,还有很多应用程序)

如果可能的话,我希望将其提取为一个数据块(字节[]),然后将其传递给我的应用程序,在那里它可以被分解,而不是读取大小,然后是字段,然后是大小,然后是字段-这要求我的通信与我的实现过度链接

如果有一个更合适的方式来实现这个转移,请让我知道。。。欢迎您的建议。。。 任何帮助都将不胜感激。
谢谢,

关于在平台之间传递数据的建议-不要自己进行序列化/反序列化。像谷歌这样的图书馆更安全


<>编辑:如果一个有效的过线表示不重要,使用JSON(例如C++和C++)

会更简单。如果你有C++中的结构定义,你可以在C语言中定义它(它可能需要一点小数)。然后只需读取套接字的大小,并使用将其封送到c#定义的结构

/* Define you structure like this (possibly) */
struct MESSAGE
{
  [MarshalAs(UnmanageType.ByValArray, SizeConst=8)]
  byte[]    cCommand;
  [MarshalAs(UnmanagedType.LPStr)]
  string  sParameter;
};

/* Read data into an instance of MESSAGE like this */
byte[] bytes = new byte[Marshal.SizeOf(MESSAGE)];

socket.Receive(bytes, 0, bytes.Length);
IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);

try
{
    Marshal.Copy(bytes, 0, ptr, bytes.Length);
    m = (MESSAGE)Marshal.PtrToStructure(ptr, typeof(MESSAGE));
}
finally
{
    Marshal.FreeHGlobal(ptr);
}
在.NET framework中有一个/类,它将对命名管道的访问公开为一个流,这将简化您的操作

传递数据的简单解决方案是使用基于行的协议,例如,一行=一个带参数的命令:

using (NamedPipeClientStream pipeClient =
        new NamedPipeClientStream(".", "testpipe", PipeDirection.In))
{
    pipeClient.Connect();

    using (StreamReader sr = new StreamReader(pipeClient))
    {
        string command;
        while ((command = sr.ReadLine()) != null)
        {
            Console.WriteLine("Received command: {0}", command);
        }
    }
}

因为这个问题被标记为C,这里是.NET实现的链接:而且听起来不像原来的C++应用程序正在序列化任何东西,只是在套接字上发送一个字节数组。protocol buffers是一个很好的工具,但我认为它有点过分了。scottm,在我看来,它发送的是8个字符+一个字符串实例,如果复制结构的字节,几乎肯定会失败。我认为序列化在这里很重要。我想这只在.NET3.5(System.Pipes)中受支持,我使用的是2.0和良好的旧P/Invoke。。。还可以调用老式C++中的sender,然后将您的
hPipeInst
包装在
System.IO.Stream
中,这将给您带来几乎相同的好处(例如,为您做所有的
OverlappedPtr
工作)。在发送方,只需将换行符终止的字符串写入管道,不必是结构。在命令和参数之间使用分隔符?我需要能够提取这两个部分(当我打开命令以确定如何处理参数时)。例如:
“TRANS C:\\FILE.txt C:\\NewFolder\FILE.txt\r\n”
这对可变长度字符串(sParameter)也有效吗?我在消息结构中添加了另一个MarshalAs属性,但它应该有效。在您的专业意见中,这是一种好方法吗?正如我提到的,我创建了这个结构,因为我认为它是一个不错的选择——但是如果有更好的方法来解决我的问题,我会洗耳恭听……@Shaitan00:在我看来,使用编组对于这个任务来说有点过大。我建议使用基于行的协议(如果您只有简单的命令)或适当的序列化机制(如协议缓冲区)。@Shaitan00,项目中没有足够的信息来决定这是否是一个好的选择。是否每个套接字连接只发送一个命令,是否存在双向通信等。如果您现在正在编写双方,那么您可能应该使用dtb的答案。如果您试图处理遗留代码,但无法控制通信方式,请使用我的。