извлечь IP из буфера байтов

0

Если у меня есть буфер, содержащий эти байты:
510175126-94-51080

Как я могу извлечь часть 75126-94-51 из него (это ip) и напечатать правильный IP? Заранее спасибо.

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

edit: это мой вывод: 5 1 0 1 75 126 -94 -51 0 80

  • 3
    Всегда ли строка длиной 18 символов? Что делать, если последняя часть 12221-94-51? это неоднозначно. Что вы подразумеваете под "правильным IP"? Достаточно ли 75126-94-51 или вы хотите 75.126.94.51 ? Вы должны предоставить больше тестовых случаев.
  • 0
    Извините, я забыл сказать, что хочу в c / c ++.
Показать ещё 12 комментариев
Теги:
network-programming

4 ответа

2
Лучший ответ

В вопросе отсутствует много информации. Итак, вы читаете ответ сервера из протокола SOCKS. Во-первых, буфер не должен и не должен иметь фиксированный размер 10 байт. Он имеет 10 байтов, если ваш адрес - IPv4 (который, по общему правилу, был исчерпан несколько дней назад, время подумать о IPv6). Если источник имеет 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;
}
  • 0
    Могу ли я использовать inet_ntoa? для Windows, я думаю, inet_ntop только для Windows?
  • 0
    ааа, подожди, есть эквивалент в windows
Показать ещё 4 комментария
0

Если у вас есть следующий буфер:

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

И вы хотите его в 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 используйте ntohl и ntohs, чтобы преобразовать порядок байтов сети в порядок байтов хоста.

  • 0
    Профсоюзы не должны работать так. Вы можете получить доступ только к последнему участнику, которому вы написали. Если вы замените «union» на «struct», ваше приложение должно все еще работать (двоично несовместимо, но все еще работает).
  • 0
    @Джулиано: Полагаю. Альтернативой является приведение указателя к типу символа. Конечный результат такой же.
0

Как вы получаете этот буфер? Является ли это частью struct sockaddr_in?

Вы показываете десятичный дамп байтов, начинающийся с самого нижнего адреса буфера?

То, что вы хотите сделать, это получить указатель на базовый (память) адрес части IP-адреса и использовать ntohl() для перевода его в порядок байтов хоста, а также использовать ntohs для перевода порта 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));
  • 0
    Я не знаю, как сделать, как вы говорите. Я использую sockaddr_in для инициализации сокета, а буфер имеет тип char *. Вы можете помочь ?
  • 0
    я использовал inet_ntoa, потому что у меня нет inet_ntop, поэтому я сделал это: struct sockaddr_in server; cout << inet_ntoa (server.sin_addr); но это только дает мне 0.0.0.0
Показать ещё 1 комментарий
0

В Python:

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

print output
  • 0
    Да, в Python это просто :) я забыл сказать, в C / C ++
  • 0
    @vBx: вышесказанное легко переводится в методы std :: string в C ++; проблема в том, являются ли предположения действительными.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню