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

时间:2009-08-25 14:50:06

标签: 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;
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 MESSAGE是我提出的,这意味着如果不同的格式在重建中有用(例如添加sParameter的长度?),可以更改它,我只需要一个COMMAND和PARAMETER来被转移到一个区块(如果可能的话)。

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

例如: COMMAND = TRANS

PARAMETER = C:\ FILE.txt C:\ NewFolder \ FILE.TXT

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

如果可能的话,我想把它作为一大块数据(byte [])提取出来然后传递给我的应用程序,在那里它可以被分解,而不是读取大小的扇形,然后是字段,然后是大小,然后是一个字段 - 要求我的沟通与我的实现过度联系。

如果有更合适的方式来实施此转让请告诉我...欢迎提出建议...... 任何帮助将非常感激。 谢谢,

3 个答案:

答案 0 :(得分:1)

在平台之间传递数据的建议 - 不要自己进行序列化/反序列化。像Google Protocol Buffers这样的图书馆将是一个更安全的赌注。

编辑:如果有效的线上表示并不重要,那么使用JSON会更简单(例如Json.NET用于C#而JsonCpp用于C ++)

答案 1 :(得分:1)

如果你在c ++中有结构的定义,你可以在c#中定义它(它可能需要一点点)。然后只需读取套接字的大小并使用Marshal.PtrToStructure将其编组为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);
}

答案 2 :(得分:0)

.NET框架中有一个NamedPipeClientStream / NamedPipeServerStream类,它将对命名管道的访问作为Stream公开,这可以简化您正在做的事情。

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

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);
        }
    }
}