从字节缓冲区中提取IP

时间:2011-02-03 14:02:18

标签: c++ c network-programming

如果我有一个包含这个字节的缓冲区:
510175126-94-51080

如何从中提取75126-94-51部分(即IP)并打印正确的IP? 提前致谢。

for(int i = 0; i < bytes_recv; i++)
{
cout << static_cast<int>(temp[i]);
}
cout << endl;

编辑:这是我的输出:5 1 0 1 75 126 -94 -51 0 80

4 个答案:

答案 0 :(得分:2)

问题中缺少很多信息。因此,您正在阅读SOCKS协议的服务器回复。首先,缓冲区不应该也不会有10个字节的固定大小。如果您的地址是IPv4(前几天恰好用尽了,是时候考虑IPv6),它有10个字节。如果源具有IPv6地址,则服务器响应的大小不同。

RFC 1928第6节开始,服务器回复的格式为:

+----+-----+-------+------+----------+----------+
|VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1  |  1  | X'00' |  1   | Variable |    2     |
+----+-----+-------+------+----------+----------+

请注意,地址字段的大小可变。对于IPv4,具体来说,ATYP == 0x01和BND.ADDR的大小为4,这使得1 + 1 + 1 + 1 + 4 + 2 = 10个字节。但你应该考虑其他尺寸是可能的,特别是如果ATYP == 0x03,这使得BND.ADDR的长度确实可变。

所以,回答你的问题,考虑到你在char buffer[]数组(或指针)中有这些字节,你必须首先检查地址的类型,然后像这样提取它:

#include <arpa/inet.h>

switch (buffer[3]) {
  case 0x01: {    /* IPv4 address */
    char result[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv4: " << result << "\n";
    break;
  }

  case 0x04: {    /* IPv6 address */
    char result[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, (void*)(&buffer[4]), result, sizeof result);
    std::cout << "IPv6: " << result << "\n";
    break;
  }

  default:
    std::cout << "Unsupported format.\n";
    break;
}

答案 1 :(得分:0)

在Python中:

input = '510175126-94-51080'
output = input[4:-3]

print output

答案 2 :(得分:0)

你是如何得到这个缓冲区的?它是struct sockaddr_in的一部分吗?

您是否显示从缓冲区的最低地址开始的十进制字节转储?

您要做的是获取指向IP地址部分的基址(内存)地址的指针,并使用ntohl()将其转换为主机字节顺序,同样使用ntohs来翻译port addr。

修改

假设你有

stuct sockaddr_in foo;
char str[16];
// do some stuff that initializes foo, e.g. a call to accept() returns

您可以使用

以点分四方形式提取IP地址
inet_ntop(AF_INET, &(foo.sin_addr), str, sizeof(str));

答案 3 :(得分:0)

如果您有以下缓冲区:

buffer[10] = {5, 1, 0, 1, 75, 126, 162, 205, 80, 00};

你想要它在C / C ++中。我会定义一个结构,如下所示:

#pragma pack(1)
struct buffer_s {
    uint8_t  version;
    uint8_t  reserve_1;
    uint8_t  atype;
    uint32_t ip;
    uint16_t port;
};
#pragma pack()

然后把它放在一个联盟中:

union buffer_u {
    char buffer[10];
    struct buffer_s data;
};

现在您可以声明union buffer_u buf并将字节读入buf.buffer。然后,对于ip和port字段,使用ntohlntohs将网络字节顺序转换为主机字节顺序。