Сброс соединения из-за ошибки однорангового сокета, когда клиент прерывает соединение во время записи () - PullRequest
0 голосов
/ 20 июня 2020

Мой сервер отправляет большой файл клиенту (веб-браузеру), но когда я обновляю sh свою страницу, я получаю сброс соединения из-за ошибки узла , и программа завершается. Я ожидаю, что сервер получит новое соединение.

 while (true)
    {
        check((new_socket = accept(server_fd, (struct sockaddr *)&address,

                                   (socklen_t *)&addrlen)),
              "accept_failed");
        read(new_socket, buffer_recv, 1024);
        printf("%s\n", buffer_recv);
        T = std::thread(handle_connection, new_socket);
        T.detach();
    }

handle_connection содержит

while (file.read(&buffer[0], 1024))
    {
        s = file.gcount();
        content = chunk::make_chunk(buffer, s);
        check(write(new_socket, &content[0], content.size()), "Write_error");
    }

, где проверка - это простая функция обработки ошибок и строка возврата make_chunk. Как я могу сделать сервер из не выходить и продолжать прослушивание подключения, пожалуйста, ответьте, я новичок в программировании сокетов

1 Ответ

1 голос
/ 20 июня 2020

Да, вы можете использовать send() с MSG_NOSIGNAL или вы можете установить опцию сокета SO_NOSIGPIPE с setsockopt(). Но с минимальным изменением существующего кода и для применения настроек ко всем созданным сокетам вы можете сделать что-то вроде этого:

На странице руководства write()

EPIPE: fd подключен к каналу или сокету, конец чтения которого закрыт. Когда это произойдет, процесс записи также получит сигнал SIGPIPE. (Таким образом, возвращаемое значение записи видно, только если программа улавливает, блокирует или игнорирует этот сигнал.)

#include <signal.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>

int main()
{
    /* .... */

    sigset_t sigmask;

    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGPIPE);

    if (sigprocmask(SIG_BLOCK, &sigmask, NULL) != 0)  // get EPIPE instead
        goto handle_sigprocmask_fail;

    /* .... */

    int wr_return = write(sockfd, buf, sizeof(buf));

    if (wr_return == -1) {
        if (errno == EPIPE)
            goto handle_epipe;
    }
}
...