首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >发送到C# winsockets的c++数据包

发送到C# winsockets的c++数据包
EN

Stack Overflow用户
提问于 2014-04-19 06:56:40
回答 3查看 414关注 0票数 0

我只是试图在我的两个应用程序之间来回发送数据包,但我的字符串在c++中无法通过。这是我在c#做的事情

代码语言:javascript
复制
[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++上得到的

代码语言:javascript
复制
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,它是结构中的第一个。那个总是能通过的。我遗漏了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-19 08:03:49

尽管我从未尝试过这样的方法,但我认为您不能简单地使用winsock在两个不同的应用程序之间共享数据,然后只传递指针。内存在两者之间受到保护。

您将需要将数据序列化为内存流。对字符串使用适当的类和编码等。然后在您的C++应用程序中反序列化它。

为您的c#应用程序尝试下面这样的操作,然后在您的c++中执行逆操作,它将工作。相反,首先要读取这4个字节,然后告诉我们需要为字符串读取多少.读字符串..。继续到下一个,直到找到文件标记结束为止。

代码语言:javascript
复制
            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
EN

Stack Overflow用户

发布于 2014-04-19 07:24:10

你有几个问题:

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

在C++中,数据包应定义为:

代码语言:javascript
复制
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];
    // ...
};
票数 0
EN

Stack Overflow用户

发布于 2014-04-19 09:47:34

问题是您将字符串作为指针传递。指针仅在同一进程中有效。如果您的C#是2.0或更高版本,请将您的结构更改为:

代码语言:javascript
复制
[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[??];
}
代码语言:javascript
复制
#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++都必须是相同的大小。不要忘记在每个字符串的末尾添加空字符。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23166974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档