Можете ли вы объяснить, как работает эта функция ip_to_string? - PullRequest
1 голос
/ 05 мая 2010
#define IPTOSBUFFERS    12
char *iptos(u_long in)
{
    static char output[IPTOSBUFFERS][3*4+3+1];
    static short which;
    u_char *p;

    p = (u_char *)∈
    which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
    _snprintf_s(output[which], sizeof(output[which]), sizeof(output[which]),"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return output[which];
}

Есть что-то, чего мне не хватает, чтобы понять это?

Ответы [ 2 ]

2 голосов
/ 05 мая 2010

Аннотировано ниже для вашего удовольствия:

// This is the number of IP string buffers.
#define IPTOSBUFFERS 12

char *iptos(u_long in)
{
    // 12 buffers, each big enough to hold maximum-sized IP address
    //   and nul terminator.
    static char output[IPTOSBUFFERS][3*4+3+1];

    // Last buffer used.
    static short which;

    // Get uns. char pointer to IP address.
    u_char *p;
    p = (u_char *)∈

    // Move to next string buffer, wrapping if necessary.
    which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);

    // Output IP address by accessing individual unsigned chars in it.
    _snprintf_s(output[which], sizeof(output[which]), sizeof(output[which]),
        "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);

    // Return the current buffer.
    return output[which];
}

Это работает, потому что представление адреса IPv4 является 32-битным значением в памяти, и каждый из четырех сегментов занимает один октет каждый. Поэтому относительно просто преобразовать адрес 32-разрядного целого в массив из четырех символов, а затем использовать этот массив для извлечения отдельных сегментов. Это, конечно, основано на типах данных, имеющих определенную битовую ширину, так что это не так переносимо.

Странная вещь - круговая очередь с 12 IP-адресами. Возможно, так можно было получить до 12 IP-адресов за раз без перезаписи строк, хотя я не думаю, что когда-либо сталкивался с ситуацией, когда было больше двух (может быть, три для прокси или сквозного сервера) требуется в то же время. Я не думаю, что это для безопасности потоков, так как модификация which опасна в многопоточной среде.

1 голос
/ 05 мая 2010

Вот ответ, основанный на том, что кажется непонятным из комментариев.

IP-адрес часто представляется внутри как 32 бита.Он часто представлен в виде 4 десятичных полей в диапазоне от 0 до 255. Чтобы преобразовать десятичное представление в 32-разрядное, просто преобразуйте поля из десятичного в двоичное (или шестнадцатеричное) слева направо и объедините их.*

Таким образом, 1.2.3.4 становится полями 0x01, 0x02, 0x03 и 0x04.Таким образом, 32-битное (беззнаковое длинное) представление из них: 0x01020304.Конечно, это также зависит от порядка следования байтов ...

Чтобы напечатать 32-битный адрес в виде строки, просто посмотрите на каждый из четырех наборов из 8 бит, которые его составляют, и напечатайте ихв виде десятичных целых чисел с точками между ними.

...