发送到C++winsockets的C#数据包
C# packet sent to c++ winsockets
本文关键字:数据包 C++winsockets 更新时间:2023-10-16
我只是想在我的两个应用程序之间来回发送数据包,但我的字符串在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在两个不同的应用程序之间共享数据,然后只传递指针。内存在两者之间受到保护。
您需要将数据序列化为内存流。将适当的类与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...
}
您有几个问题:
- 在C#端,封送大小定义为32字节,而不是4+2*8*4=68字节。最好删除
StructureLayout
中的Size
字段 - 在C++中,您定义了
char
而不是wchar_
t,在C#端有Unicode字符串 - 您定义了指针而不是数组,因此:
sizeof(Packet
)为20- 数据包结构外部的
memcpy
副本 - 您的代码试图访问无效内存,因为它将字符串值转换为指针
在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++的大小必须相同。不要忘记在每个字符串的末尾添加null字符。
相关文章:
- boost::asio UDP 广播客户端仅接收"fast"数据包
- 如何使用发送数据包所花费的时间计算两个节点之间的距离?
- 发送固定大小的 UDP 数据包
- pcap_handler回调仅在使用 NPCAP v0.9991 时包含空数据包
- 在 c++ 中解析数据包数据的最佳方法是什么?
- 接受函数在发送数据包时等待
- 如何在 omnet++ 中发送自定义数据包?
- 数据包访问实践
- 在C++中创建一个简单的数据包路由器,如何跟踪"客户端"?
- 德拉吉诺 LG01-S 收到异常数据包并停止工作
- 将数据包从C++服务器发送到NodeJs服务器时出现MessagePack解码错误
- 使用C++将UDP数据包存储在Structure中
- FFmpeg av_read_frame从音频流返回数据包
- 为什么操作系统正在更改我的数据包的指定传出端口
- 是否可以将多个结构作为一个数据包存储在一个函数中,然后传递给其他函数并在那里提取?
- recvfrom 只收到几个数据包,之后它进入等待状态
- 如何调试由 C++ 编写的 npm 数据包
- 如何在INET的应用层中发送广播数据包
- C++ 将字符串数据包转换为 iphdr语言 - 字符串数据包的格式应该是什么?
- 不同的数据包,联合 - 正确的用法\验证?