Проверьте, подключен ли сокет или нет.

У меня есть приложение, которое должно отправить некоторые данные на сервер в какое-то время. Простым способом было бы закрыть соединение, а затем снова открыть его, когда я хочу что-то отправить. Но я хочу сохранить соединение открытым, поэтому, когда я хочу отправить данные, я сначала проверяю соединение, используя эту функцию:

bool is_connected(int sock)
{
    unsigned char buf;
    int err = recv(sock,&buf,1,MSG_PEEK);
    return err == -1 ? false : true;
}

Плохая часть заключается в том, что это не работает. Он зависает, когда нет данных для получения. Что я могу сделать? Как я могу проверить, все ли соединение открыто?

Ответы

Ответ 1

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

Чтобы проверить статус, используйте:

int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);

Ответ 2

Вам нужно включить неблокирующее поведение, установив O_NONBLOCK с помощью fcntl. Одним простым, но нестандартным способом делать неблокирующее чтение было бы использовать:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);

После этого вы должны проверить errno, если он терпит неудачу. Он может выйти из строя с помощью EAGAIN или может завершиться с ошибкой EBADF или ENOTCONN и т.д.


Очевидно, что самым простым и чистым способом борьбы с этим было бы избежать "забывания", если сокет подключен или нет. Вы заметите, что сокет будет отключен после того, как a recv вернет 0 или send вернет EPIPE.

Ответ 3

Использование по умолчанию TCP не позволяет очень своевременно обнаруживать мертвые сокеты (вне нормального закрытия), поэтому я предлагаю, чтобы функция "is_connected", подобная этой, в значительной степени бесполезна для всех практических целей. Подумайте о том, как реализовать накладной уровень и отслеживать его, если он жив, на основе своевременных ответов (или их отсутствия).

edit: после публикации я вижу ссылку BoBTFish, которая фактически является тем же самым.