开发者

How to Send C++ Struct Message from C# Socket?

开发者 https://www.devze.com 2023-03-28 12:15 出处:网络
This is the C++ Message that i need to pass from C#: structLoginMessage:public开发者_Python百科 NMessage

This is the C++ Message that i need to pass from C#:


struct   LoginMessage:public开发者_Python百科 NMessage
{

 char   szUser[ 16 ];
 char   szPass[ 16 ];

    LoginMessage()
    {
       msgId   = CTRL_SESSION_LOGIN;
       msgSize = sizeof( LoginMessage );
    }

};

struct NMessage
{
    DWORD           msgSize;
    union
    {
        DWORD       msgId;
        struct
        {
            BYTE    msgId0;
            BYTE    msgId1;
            BYTE    msgId2;
            BYTE    msgId3;
        };
    };

    NMessage() 
    {
    }

    BOOL IsLegal()
    {
        return msgSize>=sizeof(NMessage) && msgSize

What is the equivalent of this in C# so that C++ can understand this message? Sample code is greatly appreciated.


To answer my own question..


        [StructLayout(LayoutKind.Sequential)]
        public struct LoginMessage
        {
            public int msgSize;
            public int msgId;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string szUser;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string szPass;
        }

It is important to take note of the sequence of the class properties so that the byte array you send to c++ is exactly the same as what it expects.


Have a look at this. it's a nice marshaling guid.


Take a look at the StructLayout attribute on MSDN. There is a good example on that page on how to create a struct that can be marshalled correctly. You can also look at http://www.pinvoke.net to see different examples of how the Windows API structs are defined to be marshaled. Once you have the struct defined right, you should be able to use Marshal.StructureToPtr or Marshal.PtrToStructure. Here's a short article on it: http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx


I usually manually serialize data using something like this.

class NMessage {

    byte[] buffer;

    //ctor to create a new message for sending.
    public NMessage(int nSize) {
         buffer = new byte[nSize];
         Buffer.BlockCopy(BitConverter.GetBytes(nSize), 0, buffer, 0, sizeof(UInt32));
    }

    //ctor to create msg from received data.
    publix NMessage(byte[] buffer) {
        this.buffer = buffer;
    }

    public UInt32 MessageId {
        get { return BitConverter.ToUInt32(buffer, 4);
        set { Buffer.BlockCopy(BitConverter.GetBytes(value), 0, buffer, 4, sizeof(UInt32)); }
    }

    ...        

    public Byte MessageId2 {
        get { return buffer[6]; }
        set { buffer[6] = value; }
    }

    ...

    public UInt32 Size {
        get { return BitConverter.ToUInt32(buffer, 0) }
    }

    public Byte[] Buffer {
        get { return buffer; }
    }
}

class LoginMessage : NMessage {

    Encoding encoding = new ASCIIEncoding(); //or whatever encoding you need.

    public LoginMessage() : base(16 + 16) {
        this.MessageId = CTRL_SESSION_LOGIN;
    }

    public LoginMessage(NMessage message) : base(message.Buffer) {
    }

    public string User {
        get { return encoding.GetString(buffer, 8, 16); }
        set { Buffer.BlockCopy(encoding.GetBytes(value), 0, buffer, 8, 16);
    }

    public string Pass {
        get { return encoding.GetString(buffer, 24, 16); }
        set { Buffer.BlockCopy(encoding.GetBytes(value), 0, buffer, 24, 16);
    } 
 }

So you simply create you new message, set it's data, then send the Buffer property.

Send((new LoginMessage {
              User = "user",
              Pass = "pass",
          }).Buffer);

On the receiving end, if you have enough data, you can build the message from the byte[] you receive.

byte[] recvBuf = new byte[MAX_RECV];
int recvSize = Receive(recvBuf);
...
var message = new NMessage(recvBuf);
if (message.MessageId == CTRL_SESSION_LOGIN)
    var login = new LoginMessage(message);
    var user = login.User;
    ...

That's just a rough overview anyway, the code obviously needs a cleanup as I reduced it to only demonstrate the idea.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号