извлечь IP из буфера байтов - PullRequest
0 голосов
/ 03 февраля 2011

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

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

for(int i = 0; i < bytes_recv; i++)<br> {<br> cout << static_cast<int>(temp[i]);<br> }<br> cout << endl;
редактировать: это мой вывод: 5 1 0 1 75 126 -94 -51 0 80

Ответы [ 4 ]

2 голосов
/ 03 февраля 2011

Много информации отсутствует в вопросе. Итак, вы читаете ответ сервера по протоколу 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 голосов
/ 03 февраля 2011

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

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

Что вы хотите сделать, это получить указатель на базу(память) адрес части IP-адреса и используйте ntohl() для преобразования его в порядок байтов хоста, а также используйте ntohs для преобразования адреса порта.

edit

Предположим, у вас есть

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 голосов
/ 03 февраля 2011

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

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

0 голосов
/ 03 февраля 2011

В Python:

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

print output
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...