чтение пакета данных Ethernet из необработанных сокетов с использованием recvfrom() в режиме MSG_DONTWAIT

Я использую необработанные сокеты для отправки и получения пакетов данных Ethernet в C, используя recvFrom(). Я хочу читать в неблокирующем режиме, поэтому я использую MSG_DONTWAIT. Но recvFrom() всегда возвращает -1, даже если пакет получен или нет. Я новичок в программировании на C. Я могу получить свою полезную нагрузку, но всегда получаю сообщение «Получить ресурс временно недоступен».

Фрагмент кода:

    if ((sock = socket(AF_PACKET, SOCK_RAW, htons(0x8851))) < 0) { 
       perror("ERROR: Socket");
       exit(1);
    }


    while(1) {
       int flag=0;
       n=recvfrom(sock, buffer, 2048, MSG_DONTWAIT, NULL, NULL);

       if (n == -1) {
           perror("ERROR: Recvfrom");
           close(sock);
           flag=1;

       } 

       if (flag==0)  {
        // Read Packet

       }
    }

person Tejzeratul    schedule 18.03.2015    source источник
comment
Почему вы создаете новые сокеты в цикле?   -  person user253751    schedule 18.03.2015
comment
Кроме того, какую ошибку он печатает?   -  person user253751    schedule 18.03.2015
comment
Я добавил сообщение об ошибке в вопрос. Я тоже каждый раз закрываю.   -  person Tejzeratul    schedule 18.03.2015
comment
Как вы думаете, что должно произойти, если пакет получен, а у вас нет сокета? (Ответ: он будет обрабатываться как любой пакет, но ваша программа не получит копию, потому что у нее нет необработанного сокета)   -  person user253751    schedule 18.03.2015
comment
Я хочу, чтобы пакет читался только тогда, когда пакет получен в сокете, чего не происходит, потому что recvfrom() всегда возвращает одно и то же значение, поэтому нет условия для проверки того, получен ли пакет или нет.   -  person Tejzeratul    schedule 18.03.2015
comment
Он всегда возвращает -1 и EAGAIN, потому что никогда не получает пакет...   -  person user253751    schedule 18.03.2015
comment
Спасибо, я понял вашу точку зрения. Я неправильно понял поведение recvfrom().   -  person Tejzeratul    schedule 18.03.2015


Ответы (1)


Если вы используете аргумент MSG_DONTWAIT для recvfrom(), системный вызов всегда немедленно возвращает значение независимо от того, есть ли какие-либо данные для чтения. Если данных нет, возвращаемое значение равно -1, и тогда для errno будет установлено значение EAGAIN. В вашем приложении я не совсем уверен, что MSG_DONTWAIT является правильным выбором. Если единственное, что вы делаете, это читаете пакеты из этого сокета, вам не следует использовать MSG_DONTWAIT. Итак, ваша программа на практике будет печатать множество сообщений об ошибках в цикле. Если вы удалите это сообщение об ошибке для случая, когда errno == EAGAIN, ваша программа будет немного лучше, но не намного лучше: она будет вращаться в цикле, потребляя все ресурсы процессора.

Однако если вы одновременно читаете данные из нескольких файловых дескрипторов, правильным выбором будет использование неблокирующего ввода-вывода. Но вместо вашего цикла у вас должен быть цикл, который опрашивает готовность нескольких файловых дескрипторов, используя select(), poll() или epoll_wait(). Поскольку вы работаете в Linux, я настоятельно рекомендую epoll_wait(), так как это наиболее масштабируемый подход. Дополнительную информацию см. в справочных страницах epoll, epoll_wait и epoll_create для Linux.

Я настоятельно рекомендую пока не использовать MSG_DONTWAIT и проверить, возвращается ли вызов функции. Если он никогда не возвращается, это означает, что он не получает никаких пакетов.

person juhist    schedule 19.03.2015