简体   繁体   English

将C#数据包发送到C ++ Winsockets

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

I am just trying to send packets back and forth between my two apps but my strings aren't getting through in c++. 我只是想在两个应用程序之间来回发送数据包,但是我的字符串无法在c ++中通过。 here's what I'm doing in 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);

and here's what I got in c++ 这就是我在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);

The only value that seems to work is the packet_type which is the first one in the struct. 似乎起作用的唯一值是packet_type,它是结构中的第一个值。 that one always comes through. 那个总是来的。 What am I missing? 我想念什么?

Even though I never tried such approach, I think you cannot simply share data between 2 distinct applications using winsock, then just passing pointer. 即使我从未尝试过这种方法,我认为您也不能简单地使用Winsock在2个不同的应用程序之间共享数据,然后仅传递指针。 Memory is protected between both. 两者之间的内存均受保护。

You will need to serialize your data to a memory stream. 您将需要将数据序列化到内存流。 Using the proper classes with Encoding etc. for your strings. 对字符串使用正确的带有Encoding等的类。 Then deserialize it in your C++ app. 然后在您的C ++应用程序中反序列化它。

Try something like below for your c# application, then do the inverse in your c++, it will work. 为您的C#应用​​程序尝试类似下面的操作,然后在您的C ++中执行相反的操作,它将起作用。 The other way round would first read the 4 bytes, to tell how much more to read ahead for the string.... the read the string... the proceed to the next one, until an end of file marker is found. 反之,则首先读取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...
        }

You have several problems: 您有几个问题:

  1. On C# side the marshal size is you defined as 32 bytes instead of 4 + 2 * 8 * 4 = 68 bytes. 在C#端,将元数据大小定义为32个字节,而不是4 + 2 * 8 * 4 = 68个字节。 It would be better to remove Size field in StructureLayout 最好在StructureLayout删除Size字段
  2. In C++ you defined char instead of wchar_ t, on the C# side there are Unicode strings 在C ++中,您定义了char而不是wchar_ t,在C#端有Unicode字符串
  3. You defined pointers instead of array so: 您定义了指针而不是数组,因此:
    • sizeof(Packet ) is 20. sizeof(Packet )为20。
    • memcpy copies outside the Packet struct memcpy在Packet结构外部复制
    • Your code tries to access invalid memory, since it converts string values into pointers. 您的代码尝试访问无效的内存,因为它会将字符串值转换为指针。

In C++ Packet should be defined as following: 在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];
    // ...
};

The problem is you pass string as pointer. 问题是您将字符串作为指针传递。 Pointer is only valid in the same process. 指针仅在同一过程中有效。 If your C# is 2.0 or above, change your struct to this: 如果您的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)

Replace ?? 替换?? with the size you want, both C# and C++ must be the SAME size. 使用所需的大小,C#和C ++的大小都必须相同。 And don't forget to add null character at the end of every string. 并且不要忘记在每个字符串的末尾添加空字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM