如何正确地将C ++ ulong 4字节IP地址转换为C#类型?

时间:2017-05-09 09:06:12

标签: c# c++ networking

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

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 时遇到异常。

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

1 个答案:

答案 0 :(得分:1)

此处的问题是您的addressx小于零或大于0x00000000FFFFFFFF。

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

您需要做的是使用地址的int address = BitConverter.ToInt32(temp, 0); 形式调用采用int的版本:

NetworkToHostOrder()

现在当你致电int时,你会得到一个(可能是否定的)uint,你需要将其转换为uint addressx = (uint) IPAddress.NetworkToHostOrder(address);

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

现在这应该有效:

$params = array(
    "type"            => 'Get',
    "get_param"       => 'Installments',
    "language"        => 'tr',
    "client_ip"       => $_SERVER['REMOTE_ADDR']

);

$api_url =  'https://blabla/portal/web/api/v1';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
$response = curl_exec($ch);


echo '<pre>';
var_dump($response);
var_dump(curl_getinfo($ch));
var_dump(curl_errno($ch));
var_dump(curl_error($ch));
echo '</pre>';