簡體   English   中英

將C#數據包發送到C ++ Winsockets

[英]C# packet sent to c++ winsockets

我只是想在兩個應用程序之間來回發送數據包,但是我的字符串無法在c ++中通過。 這就是我在C#中所做的

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Size=32)]
public struct Packet
{
    public uint packet_type;
    [MarshalAs(UnmanagedType.LPWStr, SizeConst = 8)]
    public string file_name;
    [MarshalAs(UnmanagedType.LPWStr, SizeConst = 8)]
    public string template_name;
    [MarshalAs(UnmanagedType.LPWStr, SizeConst = 8)]
    public string file_name_list;
    [MarshalAs(UnmanagedType.LPWStr, SizeConst = 8)]
    public string file_buffer;
}
var data = new Packet
{
    packet_type = (uint)action,
    file_name = fileName + Char.MinValue,
    file_name_list = "" + Char.MinValue,
    template_name = "" + Char.MinValue
};
byte[] buffer = new byte[Marshal.SizeOf(typeof(Packet))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(data, handle.AddrOfPinnedObject(), false);
handle.Free();
var bytesSent = _client.Client.Send(buffer);
byte[] buffer = new byte[Marshal.SizeOf(typeof(Packet))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(data, handle.AddrOfPinnedObject(), false);
handle.Free();
var bytesSent = _client.Client.Send(buffer);

這就是我在C ++中得到的

struct Packet {

unsigned int packet_type;
char* file_name;
char* template_name;
char* file_name_list;
char* file_data;

void serialize(char * data) {
    memcpy(data, this, sizeof(Packet));
}

void deserialize(char * data) {
    memcpy(this, data, sizeof(Packet));
}
};

char network_data[MAX_PACKET_SIZE];
recv(curSocket, buffer, MAX_PACKET_SIZE, 0);

似乎起作用的唯一值是packet_type,它是結構中的第一個值。 那個總是來的。 我想念什么?

即使我從未嘗試過這種方法,我認為您也不能簡單地使用Winsock在2個不同的應用程序之間共享數據,然后僅傳遞指針。 兩者之間的內存均受保護。

您將需要將數據序列化到內存流。 對字符串使用正確的帶有Encoding等的類。 然后在您的C ++應用程序中反序列化它。

為您的C#應用​​程序嘗試類似下面的操作,然后在您的C ++中執行相反的操作,它將起作用。 反之,則首先讀取4個字節,以告訴該字符串要讀取的字節數更多。...讀取的字符串...繼續進行下一個字節,直到找到文件標記的末尾。

            string myString = "abc";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(myString);


        using (MemoryStream ms = new MemoryStream())
        {

            ms.Write(BitConverter.GetBytes(buffer.Length), 0, 4);
            ms.Write(buffer, 0, buffer.Length);

            //... rest of code...
        }

您有幾個問題:

  1. 在C#端,將元數據大小定義為32個字節,而不是4 + 2 * 8 * 4 = 68個字節。 最好在StructureLayout刪除Size字段
  2. 在C ++中,您定義了char而不是wchar_ t,在C#端有Unicode字符串
  3. 您定義了指針而不是數組,因此:
    • sizeof(Packet )為20。
    • memcpy在Packet結構外部復制
    • 您的代碼嘗試訪問無效的內存,因為它會將字符串值轉換為指針。

在C ++中,數據包應定義如下:

struct Packet {
    unsigned int packet_type;
    wchar_t file_name[8];
    wchar_t template_name[8];
    wchar_t file_name_list[8];
    wchar_t file_data[8];
    // ...
};

問題是您將字符串作為指針傳遞。 指針僅在同一過程中有效。 如果您的C#為2.0或更高版本,請將您的結構更改為此:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct Packet
{
    public uint packet_type;
    public fixed char file_name[??];
    public fixed char template_name[??];
    public fixed char file_name_list[??];
    public fixed char file_buffer[??];
}
#pragma pack(push, 1)
struct Packet {
    unsigned int packet_type;
    wchar_t file_name[??];
    wchar_t template_name[??];
    wchar_t file_name_list[??];
    wchar_t file_data[??];

    void serialize(char * data) {
        memcpy(data, this, sizeof(Packet));
    }

    void deserialize(char * data) {
        memcpy(this, data, sizeof(Packet));
    }
};
#pragma pack(pop)

替換?? 使用所需的大小,C#和C ++的大小都必須相同。 並且不要忘記在每個字符串的末尾添加空字符。

暫無
暫無

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

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