read () выходит из программы, когда нечего читать - PullRequest
0 голосов
/ 19 июня 2020

Я делаю клиент-серверную программу с многопоточным сервером и использую сокеты для связи.

Все работает нормально для части чтения / отправки, но во время тестирования я увидел, что сервер выходит когда функции read () нечего читать, вместо того, чтобы просто ждать бесконечно.

Останавливается не только поток, но и вся программа. Это нормальное поведение? Разве функция read () не должна блокировать?

Попытка сделать минимальное представление о том, что я делаю:

Сервер:

void admin_process_server(int sockcomm) // executed in a thread
{

char buff[256];
bzero(buff, sizeof(buff));

while(1){

    // definir le nombre de joueurs

    write_buff("NUMBER_OF_USERS", &buff);
    write(sockcomm, buff, sizeof(buff));

    read_client(&buff, sockcomm);
    printf("Message recu - Socket %d : %s, %ld\n", sockcomm, buff, strlen(buff));

    for (int p = 1; p <= GAME.nb_players; ++p)
    {

        write_buff("SET_USERNAME", &buff);
        write(sockcomm, buff, sizeof(buff));

        read_client(&buff, sockcomm);
        printf("Message recu - Socket %d : %s, %ld\n", sockcomm, buff, strlen(buff)); //exits here for some reasons ?

        set_player_username(p,strdup(buff));

    }
}
}

void read_client(char (*buff)[256], int sockfd)
{

    bzero(*buff, sizeof(*buff));
    int recu = read(sockfd, *buff, sizeof(*buff));
    (*buff)[recu] = '\0';

}

void set_player_username(int p, char * u)
{

    pthread_mutex_lock(&verrou_player);
    GAME.players[p].username = u;
    pthread_mutex_unlock(&verrou_player);

}

И в основном при выходе из read () клиент ничего не отправляет

Valgrind дает мне следующее:

==4759== 
==4759== Process terminating with default action of signal 13 (SIGPIPE)
==4759==    at 0x4E4D2B7: write (write.c:27)
==4759==    by 0x10962C: admin_process_server (in /home/seitnom/Documents/ESGI/ProgSysRes/_______PROJECT/Server/server)
==4759==    by 0x10927C: th_action (in /home/seitnom/Documents/ESGI/ProgSysRes/_______PROJECT/Server/server)
==4759==    by 0x4E436DA: start_thread (pthread_create.c:463)
==4759==    by 0x517C88E: clone (clone.S:95)
==4759== 
==4759== HEAP SUMMARY:
==4759==     in use at exit: 389 bytes in 5 blocks
==4759==   total heap usage: 6 allocs, 1 frees, 1,413 bytes allocated
==4759== 
==4759== LEAK SUMMARY:
==4759==    definitely lost: 0 bytes in 0 blocks
==4759==    indirectly lost: 0 bytes in 0 blocks
==4759==      possibly lost: 285 bytes in 2 blocks
==4759==    still reachable: 104 bytes in 3 blocks
==4759==         suppressed: 0 bytes in 0 blocks
==4759== Rerun with --leak-check=full to see details of leaked memory
==4759== 
==4759== For counts of detected and suppressed errors, rerun with: -v
==4759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

После более глубокого просмотра read () возвращает 0 (не знаю почему , читать нечего), и программа завершает работу при следующей отправке с сервера.

1 Ответ

2 голосов
/ 19 июня 2020

Согласно трассировке valgind, ваш код завершается при вызове write, а не read.

SIGPIPE означает, что вы пытаетесь записать в сокет или канал, который был закрыт на другом конце. Вы можете попытаться поймать или игнорировать SIGPIPE, если вы хотите чего-то отличного от простого выхода - если вы проигнорируете SIGPIPE, то системный вызов write вернет ошибку EPIPE.

В целом ваш код выглядит очень fr agile, так как вы не проверяете возвращаемые значения системных вызовов read и write на наличие ошибок или других необычных условий. Таким образом, любое необычное происшествие приведет к неправильному поведению вашей программы и выполнению чего-то необычного.

...