簡體   English   中英

如何從 C# 套接字發送 C++ 結構消息?

[英]How to Send C++ Struct Message from C# Socket?

這是我需要從 C# 傳遞的 C++ 消息:


struct   LoginMessage:public 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

C# 中的這個等價物是什么,以便 C++ 可以理解這個消息? 示例代碼非常感謝。

回答我自己的問題..


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

重要的是要注意 class 屬性的順序,以便發送到 c++ 的字節數組與預期的完全相同。

看看這個 這是一個很好的編組指南。

看看 MSDN 上的StructLayout屬性。 該頁面上有一個很好的示例,說明如何創建可以正確編組的結構。 您還可以查看http://www.pinvoke.net以查看如何將 Windows API 結構定義為編組的不同示例。 正確定義結構后,您應該能夠使用Marshal.StructureToPtrMarshal.PtrToStructure 這是一篇關於它的簡短文章: http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx

我通常使用類似的方法手動序列化數據。

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

因此,您只需創建新消息,設置它的數據,然后發送 Buffer 屬性。

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

在接收端,如果你有足夠的數據,你可以從你收到的 byte[] 構建消息。

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;
    ...

無論如何,這只是一個粗略的概述,代碼顯然需要清理,因為我將其簡化為僅演示這個想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM