/bin/dev - IT Lounge

Полная версия: Ошибка при работе с socket и fork() на сях
Вы просматриваете упрощённую версию нашего контента. Просмотр полной версии с полным форматированием.

Guest

Допустим, вы пишете сервер и хотите, чтоб он мог обслуживать несколько клиентов. Один из вариантов решения этой задачи может заключаться в использовании вызова fork() и обслуживании запроса в форке. Код может быть примерно следующим:

Код:
    int forkResult = 0;
    int aSocket = 0;
    
    do{
        aSocket = accept(listener, NULL, NULL);
        forkResult = fork();
        switch(forkResult){
            case -1:{
                printf("fork() err\n");
                break;
            }
            case 0:{
                server(aSocket);
                break;
            }
        }
    }while(forkResult>0);
Казазалось бы, что всё правильно - мы принимаем соединение, вызываем fork() и в ребёнке отправляем обрабатываться принятое соединение, а сами ждём следующее соединение. Но вот тут кроется одна маленькая неочиведность - закрытие сокета в ребёнке на самом деле не закрое сокет. Всё дело в том, что после вызова fork(), пораждается новый процесс у которого есть свой дескриптор на этот сокет. То есть на один и тот же сокет мы имеем 2 дескриптора: один в родителе, другой в ребёнке. Когда функция server() отработает и закроет сокет, то останется ещё один дескриптор(который в родителе) и сокет на самом деле не закроется. Чтоб сокет закрывался на самом деле, его нужно закрывать в обоих процессах.
Код:
    int forkResult = 0;
    int aSocket = 0;
    
    do{
        aSocket = accept(listener, NULL, NULL);
        forkResult = fork();
        switch(forkResult){
            case -1:{
                printf("fork() err\n");
                break;
            }
            case 0:{
                server(aSocket);
                break;
            }
            default:{
                close(aSocket);// закрываем сокет в родителе
            }
        }
    }while(forkResult>0);
Теперь сокет будет закрываться в родителе сразу же и останется всего один дескриптор - в ребёнке. Когда ребёнок закроет свой сокет, то на сокет не останется ни одного дескриптора и сокет будет закрыт по-настоящему.
О_о Вот это вовремя. Я как раз пару часов назад сделал не правильно. Пойду переделывать...