2015-07-17 15 views
7

Mam pytania dotyczące prawidłowego zamykania deskryptora pliku gniazda. Załóżmy, że serwer podaje inną procedurę za każdym razem, gdy akceptuje nowe połączenie. Oryginalny deskryptor pliku gniazda to sockfd, a nowy deskryptor pliku gniazda to new_sockfd.Jak prawidłowo używać gniazda zbliżonego do widelca?

sockfd = socket(...) 
bind(...); 
listen(...); 

while(1) { 
    new_sockfd = accept(...); 
    if(fork() == 0) { 
    // Child process 
    dosomething(...); 

    } 
    else { 

    } 
} 

Moje pytanie brzmi, gdzie powinniśmy umieścić close(sockfd) i close(new_sockfd). Widziałem kilka przykładów na stronie internetowej (http://www.tutorialspoint.com/unix_sockets/socket_quick_guide.htm "Obsługa wielu połączeń") umieszczają close(sockfd) w bloku if i close(new_sockfd) w bloku else. Ale po rozwidleniu nie są dwa procesy działające równolegle? Jeśli proces nadrzędny zakończy się new_sockfd, czy nie wpłynie to na proces potomny obsługi tego gniazda? Ponadto, jeśli proces potomny wykonuje close(sockfd), czy nie wpłynie to na cały program gniazda?

+0

@JosephMyers To nie jest poprawne. Deskryptor pliku jest odrębny w obu procesach. Rodzic powinien zamknąć akceptowane gniazdo: pozostaje otwarte w procesie potomnym. – EJP

+0

@EJP Zamierzam zajrzeć do tego trochę więcej i być może wrócę ze szczegółami. Bardziej zaznajomiłem się z systemami BSD, które według mojego doświadczenia z programowaniem serwerów oraz procesów powłokowych i rozwidlających ogólnie zapewniały dokładniejszą kontrolę nad tym, czy deskryptory plików i powiązane zasoby zostały zduplikowane lub udostępnione. Dziękuję za poświęcenie czasu na komentarze i zachęcenie mnie do powtórzenia tego, co zapamiętałem z doświadczenia. –

Odpowiedz

11

Podczas procesu rozwidlenia deskryptory plików są duplikowane w procesie potomnym. Jednak te deskryptory plików różnią się od siebie. Zamknięcie deskryptora pliku w elemencie potomnym nie wpływa na odpowiedni deskryptor pliku w elemencie nadrzędnym i na odwrót.

W twoim przypadku, ponieważ proces dziecko potrzebuje przyjętym gniazdo new_sockfd a proces rodzic nadal używać gniazda odsłuchu sockfd, dziecko powinno close(sockfd) (w bloku if, co nie wpływa na rodzica) i rodzica powinien close(new_sockfd) (w twoim bloku else, to nie ma wpływu na dziecko). Fakt, że rodzic i dziecko są uruchomione w tym samym czasie, nie ma na to wpływu.

+0

Oh! Teraz całkowicie rozumiem tę koncepcję. Dziękuję dbush :) – Jes

+0

@Jes Nie ma problemu. Zapraszam do [zaakceptowania tej odpowiedzi] (http://stackoverflow.com/help/accepted-answer), jeśli było to dla ciebie przydatne. – dbush

+0

Dzięki :) Właśnie to przyjąłem. – Jes

2

Rodzic powinien zamknąć akceptowane gniazdo (w bloku else): pozostaje otwarte w procesie podrzędnym, dopóki dziecko nie skończy go, w którym to momencie powinno ono samo się zamknąć.

+1

Podobnie jak rodzic zamyka akceptowane gniazdo, dziecko chce zamknąć słuchającego. – alk

+0

Cześć EJP, dzięki za życzliwą odpowiedź. Nadal jestem trochę zdezorientowany, czy to dlatego, że fork będzie również duplikował inne nowe połączenie z gniazdem, więc musimy zamknąć dwa deskryptory plików dwukrotnie? Nie jestem do końca pewien, dlaczego "pozostaje otwarty w procesie potomnym, dopóki dziecko nie skończy tego", ponieważ dwa procesy (rodzic i dziecko) działają równolegle, a new_sockfd może zostać zamknięty przez proces nadrzędny, zanim proces potomny go użyje, dobrze? – Jes

+0

@alk Lepiej utworzyć odsłuch z 'SOCK_CLOEXEC'' jeśli to możliwe. –

Powiązane problemy