Подтвердить что ты не робот

Как найти состояние соединения сокета в C?

У меня есть TCP-соединение. Сервер просто считывает данные с клиента. Теперь, если соединение потеряно, клиент получит ошибку при записи данных в трубу (сломанный канал), но сервер все равно прослушивает этот канал. Есть ли способ, который я могу найти, если соединение UP или NOT?

4b9b3361

Ответ 1

Вы можете вызвать getockopt так же, как и следующее:

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);

Чтобы проверить, вставлен ли сокет:

if (retval != 0) {
    /* there was a problem getting the error code */
    fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
    return;
}

if (error != 0) {
    /* socket has a non zero error status */
    fprintf(stderr, "socket error: %s\n", strerror(error));
}

Ответ 2

Единственный способ надежного обнаружения, если сокет все еще подключен, - это периодически пытаться отправить данные. Обычно удобнее определять пакет "ping" уровня приложения, который игнорируют клиенты, но если протокол уже определен без такой возможности, вы должны иметь возможность настраивать сокеты tcp, чтобы сделать это, установив SO_KEEPALIVE. Я связан с документацией winsock, но такая же функциональность должна быть доступна для всех стеков сокетов, подобных BSD.

Ответ 3

Параметр сокета TCP keepalive (SO_KEEPALIVE) поможет в этом сценарии и закройте серверный сокет в случае потери соединения.

Ответ 4

У меня была аналогичная проблема. Я хотел знать, подключен ли сервер к клиенту или клиент подключен к серверу. В таких обстоятельствах может оказаться полезным возвращаемое значение функции recv. Если сокет не подключен, он вернет 0 байт. Таким образом, используя это, я сломал цикл и не должен был использовать какие-либо дополнительные потоки функций. Вы также можете использовать это, если эксперты считают, что это правильный метод.

Ответ 5

get sock opt может быть несколько полезен, однако другой способ - установить обработчик сигнала для SIGPIPE. В принципе, всякий раз, когда вы разрываете соединение сокета, ядро ​​посылает сигнал SIGPIPE процессу, а затем вы можете сделать это нужным. Но это все еще не дает решения для проверки состояния соединения. надеюсь, что это поможет.

Ответ 6

Вам следует попытаться использовать функцию getpeername.

Теперь, когда соединение не работает, вы попадете в errno: ENOTCONN - Разъем не подключен. что означает для вас ВНИЗ.

else (если нет других отказов), код возврата будет 0 → , что означает UP.

ресурсы: man http://man7.org/linux/man-pages/man2/getpeername.2.html

Ответ 7

вы можете использовать макрос SS_ISCONNECTED в getsockopt(). SS_ISCONNECTED определяется в socketvar.h.

Ответ 8

Существует простой способ проверить состояние соединения сокетов с помощью вызова poll. Во-первых, вам нужно опросить сокет, имеет ли он событие POLLIN.

  • Если сокет не закрыт, и есть данные для чтения, тогда read вернется больше нуля.
  • Если новых данных в сокете нет, то POLLIN будет установлено значение 0 в revents
  • Если сокет закрыт, флаг POLLIN будет установлен в один, и read вернет 0.

Вот небольшой фрагмент кода:

int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
    perror("Unable to accept s1");
    abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
    perror("Unable to accept s2");
    abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024]; 
while (true)
{
    poll(pfd,2,5);
    if (pfd[0].revents & POLLIN)
    {
        int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
        if (sock_readden == 0)
            break;
        if (sock_readden > 0)
            write(client_socket_2, sock_buf, sock_readden);
    }
    if (pfd[1].revents & POLLIN)
    {
        int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
        if (sock_readden == 0)
            break;
        if (sock_readden > 0)
            write(client_socket_1, sock_buf, sock_readden);
    }
}

Ответ 9

Для сокетов BSD я проверил руководство Beej. Когда recv возвращает 0, вы знаете, что другая сторона отключена.

Теперь вы действительно можете спросить, что является самым простым способом обнаружить другую сторону отключения? Один из способов сделать это - иметь поток, всегда делающий recv. Этот поток сможет мгновенно сказать, когда клиент отключится.