【问题标题】:How to correctly convert C++ ulong 4 bytes IP address to C# type?如何正确将 C++ ulong 4 字节 IP 地址转换为 C# 类型?
【发布时间】:2017-05-09 09:06:11
【问题描述】:

我从 C++ 客户端向 C# 服务器发送 6 个字节的缓冲区。

ULONG addr = htonl(server->sin_addr.s_addr);
USHORT port = server->sin_port; -> Already reversed to network bytes.

char frame[sizeof(USHORT) + sizeof(ULONG)];

memcpy(frame, &port, sizeof(USHORT));
memcpy(&frame[2], &addr, sizeof(ULONG));


int result = send(s, (const char*)frame, sizeof(frame), 0);

如你所见,缓冲区包含:[2字节端口,4字节地址]


在 C# 服务器端,我将端口和地址从网络转换为主机字节。我已经检查以确保接收到的缓冲区始终为 6 个字节。

ushort port = BitConverter.ToUInt16(buffer, 0);

byte[] temp = new byte[4];
Array.Copy(buffer, 2, temp, 0, temp.Length);

uint address = BitConverter.ToUInt32(temp, 0);
long addressx = IPAddress.NetworkToHostOrder(address);

destPort = (ushort)IPAddress.NetworkToHostOrder((short)port);
destAddress = (new IPAddress(addressx).ToString());

有时,我在初始化 new IPAddress(address) 时遇到异常,ArgumentOutOfRangeException

我不明白为什么它只是有时会发生,我做错了什么?

【问题讨论】:

  • 为什么你在 IP 地址上使用htonlNetworkToHostOrder(我知道如果你想同时支持小端和大端节点,这是可移植的方式)而不是端口?
  • 当 IPv4 地址正好是 32 位时,为什么 addressx 被定义为 long(64 位?)?
  • @Jonas 我尝试将它定义为 int 并且问题是一样的:/我写道端口已经反转了。
  • 一个 Uint32 只有 4 个字节,而你想要 6 个字节。
  • 你帮的太多了。请改用 IPAddress(byte[]) 构造函数,字节顺序已被假定为网络顺序,并且 byte[] 的大小可确保您始终获得 IPv4 地址。

标签: c# c++ networking


【解决方案1】:

这里的问题是你的addressx要么小于零,要么大于0x00000000FFFFFFFF。

发生这种情况是因为当 addressuint 时,您正在调用 IPAddress.NetworkToHostOrder(address);。由于没有接受uintNetworkToHostOrder() 重载,因此将参数提升为long 并调用NetworkToHostOrder(long)。这会导致某些输入出现负值。

您需要做的是使用地址的int 形式调用采用int 的版本:

int address = BitConverter.ToInt32(temp, 0);

现在,当您调用 NetworkToHostOrder() 时,您将得到一个(可能是否定的)int 回复,您需要将其转换为 uint

uint addressx = (uint) IPAddress.NetworkToHostOrder(address);

现在应该可以了:

destAddress = (new IPAddress(addressx).ToString());

【讨论】:

  • 我在你发布它的那一刻就明白了!感谢您的回答和解释,现在更有意义了:)
猜你喜欢
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 2012-07-14
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
相关资源
最近更新 更多