Почему вновь созданный сокет доступен для чтения и записи, который отслеживается функцией select ()? - PullRequest
1 голос
/ 14 июня 2019

Я написал следующий код.Я создаю сокет и использую select() для мониторинга этого вновь созданного сокета.После вызова select() этот сокет обнаруживается как читаемый и доступный для записи.

Как объяснить это явление?Имеет ли это какое-либо отношение к сокету recvbuf / sndbuf и recvlowat / sndlowat?

#include <iostream>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>


int main()
{
    int nClientFd = socket(AF_INET, SOCK_STREAM, 0);
    if (nClientFd == -1)
    {
        std::cout << "create socket failed, errno: " << errno << std::endl;
        return -1;
    }

    fd_set readFdSet;
    FD_ZERO(&readFdSet);
    FD_SET(nClientFd, &readFdSet);

    fd_set writeFdSet;
    FD_ZERO(&writeFdSet);
    FD_SET(nClientFd, &writeFdSet);

    struct timeval stTimeout;
    stTimeout.tv_sec = 1;
    stTimeout.tv_usec = 0;

    if (select(nClientFd + 1, &readFdSet, &writeFdSet, nullptr, &stTimeout) == -1)
    {
        std::cout << "select failed" << std::endl;
        close(nClientFd);
        return -1;
    }

    if (FD_ISSET(nClientFd, &readFdSet))
    {
        std::cout << "socket is readable" << std::endl;
    }

    if (FD_ISSET(nClientFd, &writeFdSet))
    {
        std::cout << "socket is writable" << std::endl;
    }

    close(nClientFd);
    return 0;
}

Вывод:

socket is readable
socket is writable

1 Ответ

2 голосов
/ 14 июня 2019

Начнем с того, что в Linux / glibc select() задокументировано время от времени ложное сообщение о том, что дескрипторы файлов доступны для чтения, но нам не нужно полагаться на это, чтобы объяснить поведение.

Появляется основная проблемабыть таковым, что вы неверно истолковали значение select() установки дескриптора файла в одном из предоставленных наборов fd для чтения или записи.Это не обязательно означает, что данные могут быть успешно переданы через FD.Скорее это означает, что fd вошел или уже находился в состоянии, когда попытка сделать это не будет блокировать , что включает случай, когда такая попытка потерпит неудачу без блокировки.Документация Linux и особенно POSIX ясна по этому вопросу.

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

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