генерируется ОС почти как «Ой! Извините, что беспокою вас». В случае этой ошибки вы можете попробовать прочитать снова. Это не серьезная или фатальная ошибка. Я видел, как эти прерывания происходят в Linux и LynxOS от одного раза в день до 100 раз в день.

из моих проектов на Linux использует блокирующие сокеты. Вещи происходят очень последовательно, поэтому неблокирование только усложнит ситуацию. Во всяком случае, я нахожу, что частоrecv() звонок возвращается-1 с участиемerrno установлен вEAGAIN.

man Страница действительно упоминает, что это происходит для неблокирующих сокетов, что имеет смысл. При неблокировании сокет может быть или не быть доступным, поэтому вам, возможно, придется повторить попытку.

Что может привести к блокировке сокета? Могу ли я сделать что-нибудь, чтобы избежать этого?

На данный момент мой код для работы с ним выглядит примерно так (у меня есть исключение по ошибке, но помимо этого это очень простая оболочка вокругrecv()):

int ret;
do {
    ret = ::recv(socket, buf, len, flags | MSG_NOSIGNAL);
} while(ret == -1 && errno == EAGAIN);


if(ret == -1) {
    throw socket_error(strerror(errno));
}
return ret;

Это даже правильно? EAGAIN состояние поражается довольно часто.

РЕДАКТИРОВАТЬ: некоторые вещи, которые я заметил, которые могут иметь отношение к делу.

Я устанавливаю тайм-аут чтения на сокете с помощьюsetsockopts(), но он установлен на 30 секунд.EAGAINслучается чаще, чем раз в 30 секунд.КОРРЕКЦИЯ моя отладка была ошибочной,EAGAINне так часто, как я думал. Возможно, это срабатывает тайм-аут.

Для подключения я хочу иметь тайм-аут подключения, поэтому я временно установил сокет в неблокирующее состояние. Этот код выглядит так:

int      error = 0;
fd_set   rset;
fd_set   wset;
int      n;
const SOCKET sock = m_Socket;

// set the socket as nonblocking IO
const int flags = fcntl (sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);

errno = 0;

// we connect, but it will return soon
n = ::connect(sock, addr, size_addr);

if(n < 0) { 
    if (errno != EINPROGRESS) {
        return -1;
    }
} else if (n == 0) {
    goto done;
}

FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(sock, &rset);
FD_SET(sock, &wset);

struct timeval tval;
tval.tv_sec = timeout;
tval.tv_usec = 0;

// We "select()" until connect() returns its result or timeout
n = select(sock + 1, &rset, &wset, 0, timeout ? &tval : 0);
if(n == 0) {    
    errno = ETIMEDOUT;
    return -1;
}

if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) {
    socklen_t len = sizeof(error);
    if (getsockopt(SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
        return -1;
    }
} else {
    return -1;
}

done:
// We change the socket options back to blocking IO
if (fcntl(sock, F_SETFL, flags) == -1) {
    return -1;
}
return 0;

Идея состоит в том, чтобы я установил неблокирование, попытался подключиться и выбрал сокет, чтобы установить тайм-аут. И установить и восстановитьfcntl() вызовы возвращаются успешно, поэтому сокет должен снова оказаться в режиме блокировки после завершения этой функции.

Ответы на вопрос(4)

Ваш ответ на вопрос