【问题标题】:C# packet sent to c++ winsocketsC# 数据包发送到 c++ winsockets
【发布时间】:2014-04-19 06:56:40
【问题描述】:

我只是想在我的两个应用程序之间来回发送数据包,但我的字符串在 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);

似乎唯一有效的值是结构中的第一个数据包类型。那一个总是通过。我错过了什么?

【问题讨论】:

    标签: c# c++ sockets marshalling winsock


    【解决方案1】:

    尽管我从未尝试过这种方法,但我认为您不能简单地使用 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...
            }
    

    【讨论】:

    • 我尝试了所有其他答案,这是我能够开始工作的答案。除了将编码改为unicode
    • 使用这种方法我在 c++ 端遇到了问题。如果你能帮我解决这个问题,也许? stackoverflow.com/questions/23252334/…
    • 您的问题似乎得到了解答,我想您现在解决了所有问题? :)
    【解决方案2】:

    你有几个问题:

    1. 在 C# 方面,编组大小定义为 32 字节,而不是 4 + 2 * 8 * 4 = 68 字节。最好删除StructureLayout 中的Size 字段
    2. 在 C++ 中,您定义了 char 而不是 wchar_t,在 C# 端有 Unicode 字符串
    3. 您定义了指针而不是数组,因此:
      • sizeof(Packet) 是 20。
      • memcpy 复制到 Packet 结构之外
      • 您的代码尝试访问无效内存,因为它将字符串值转换为指针。

    在 C++ 中 Packet 应该定义如下:

    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];
        // ...
    };
    

    【讨论】:

      【解决方案3】:

      问题是您将字符串作为指针传递。指针只在同一进程中有效。如果您的 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++ 的大小必须相同。并且不要忘记在每个字符串的末尾添加空字符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-13
        • 2013-01-08
        • 1970-01-01
        相关资源
        最近更新 更多