Определение размера следующей UDP-дейтаграммы в очереди системы - PullRequest
0 голосов
/ 24 сентября 2010

Я хочу знать размер следующей UDP-дейтаграммы в очереди системы.

Я нашел этот вопрос с аналогичным сомнением, но с использованием форсирования.Последний ответ (по состоянию на 2010/09/23) что-то говорит об использовании getsockopt с параметром SO_NREAD в OS X, но я ничего не могу найти по этому поводу в Windows (используя Winsock).

Здесь Я обнаружил, что могу использовать ioctlsocket с FIONREAD, чтобы узнать, каков размер всей очереди, но я ничего не нашел в первой дейтаграмме.

Итак, мой вопрос: Есть ли способ определить, каков размер следующей UDP-дейтаграммы в очереди с помощью API сокетов? (я не использую boost).

Я хочу, чтобы мой код выглядел так:

char BigBuffer[ 64 * 1024 ];
void Read( void *Buf, size_t Size ) {
    size_t LengthInQueue = WhatTheSizeOfTheNextDatagram();
    if( Size < LengthInQueue ) {
         recvfrom( Socket, BigBuffer, 64*1024,  /*...*/ );
         memcpy( Buf, BigBuffer, Size );
    }
    else {
         recvfrom( Socket, Buf, size,  /*...*/ );
    }
}

Я упустил проверку ошибок и некоторые параметры ради пространства и читабельности.Я хочу избежать копирования в промежуточный буфер, когда он не нужен.

Ответы [ 3 ]

2 голосов
/ 24 сентября 2010

Если я правильно понимаю, вы просто хотите убедиться, что Buf не переполняется, но вам не нужны никакие дополнительные данные, кроме Size, поскольку вы все равно их отбрасываете. В этом случае все, что вам нужно, это:

recvfrom( Socket, Buf, size,  /*...*/ );

Остальная часть пакета автоматически отбрасывается.

Цитируется из Документы :

Для сокетов, ориентированных на сообщения, данные извлекаются из первого помещенного в очередь сообщения до размера указанного буфера. Если датаграмма или сообщение больше указанного буфера, буфер заполняется первой частью дейтаграммы, и recvfrom генерирует ошибку WSAEMSGSIZE. Для ненадежных протоколов (например, UDP) избыточные данные теряются.

0 голосов
/ 05 декабря 2011

Вызовите функцию ioctl (ioctlsocket на windows) с помощью FIONREAD:

#ifdef WIN32
    if(ioctlsocket(socket, FIONREAD, &ul) == SOCKET_ERROR) {
        return -1;
    }
    return (int)ul;
#else
    int i; // ?? int ??
    if(ioctl(socket, FIONREAD, &i) == -1) {
            return -1;
    }
    return i;
#endif
0 голосов
/ 24 сентября 2010

Вы можете pop этой дейтаграммы и рассчитать ее длину, для получения информации о существовании дейтаграммы вы можете использовать функцию select, а для получения всей дейтаграммы вы можете использовать функцию recv_from с размером буфера 64 Кб, затем эта функциябыл результат, что вы хотите.

...