2013-05-16 13 views
12

Jeśli chcę zaakceptować połączenie, zadzwonię pod numer accept, ale jak mogę odmówić połączenia?Jak mogę odmówić połączenia z gniazdem w C?

W działającym kliencie echa gniazda mam instrukcję if. Na serwerze echa, w jaki sposób mogę sprawić, aby klient echa osiągnął tę instrukcję printf?

... 
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { 
    printf("Connecting failed\n"); 
    return 1; 
} 
... 
+1

natychmiast zaakceptuj i zamknij –

+0

@BartFriederichs: to właśnie teraz robię, ale czy istnieje sposób, aby odmówić go bardziej konkretnie? – c00kiemonster

+2

Na podstawie tego, co byś odmówił? Powiedziałbym, że to, co chcesz, jest zadaniem firewalla. Większość aplikacji, o których wiem, że pracują z czarną listą, zaakceptowałaby i zamknęła. –

Odpowiedz

7

Według mojej wiedzy, nie tak działa TCP. Wywołanie accept(..) zawsze będzie zwracane wraz ze szczegółami klienta. Jest nie sposób na zerknąć na połączenie i wybiórczo odmówić.

Sposób, w jaki robisz to teraz, jest właściwie poprawny: zaakceptuj, a następnie zamknij. Jeśli masz inną strukturę wiadomości poza tą warstwą, możesz utworzyć niestandardową wiadomość "Odrzuć". Ta opcja całkowicie zależy od twojego przypadku użycia.

Jeśli szukasz odrzucenia na podstawie adresu IP, nie znajduje się on w domenie Twoich aplikacji. To jest zadanie twojej zapory ogniowej (jak mówi @Bart Friederichs). W ten sposób żądanie nie dotknie nawet stosu TCP.


Właściwie chcę ściśle jedno połączenie tylko na tym konkretnym porcie. Każde inne połączenie powinno zakończyć się niepowodzeniem w bardzo oczywisty sposób.

Nie pozwól, aby zaakceptować połączenie w twoim strumieniu sterowania. Tylko wtedy, gdy czekasz na accept, twój program czeka na połączenie z gniazdem, nigdy inaczej.

2

To może być pomocne

  1. aby zamknąć gniazdo serwera słuchania po pomyślnym accept() ing połączenia klienta i
  2. w celu przywrócenia go po nawiązaniu połączenia klient upadł z powodu jakiegokolwiek powodu.
9

Aby uzyskać pożądane zachowanie (akceptuj tylko jedno połączenie naraz, inni klienci próbują uzyskać niepowodzenie), dostępne są dwie opcje.

  • Możesz zamknąć gniazdo nasłuchu po zaakceptowaniu połączenia. Ponownie utwórz gniazdo nasłuchu po zamknięciu zaakceptowanego połączenia.

  • Możesz zamknąć nowo utworzone połączenia, jeśli trwa już połączenie. Jeśli chcesz klientowi zobaczyć reset TCP większość stosów TCP wywoła jeden jeśli włączysz opcję utrzymywał z timeout 0.

    struct linger lo = { 1, 0 };
    setsockopt(s, SOL_SOCKET, SO_LINGER, &lo, sizeof(lo));
    close(s);

+0

Czy pierwsza opcja jest rzeczywiście stosowana w praktyce? Lepiej byłoby pozostawić odsłonięte gniazdo, aby upewnić się, że zasób jest "posiadany" przez program do jego używania, dopóki jest uruchomiony. –

+0

@CraigMcQueen: Zakładam, że porty serwera zostały dostarczone, jeśli ta opcja jest używana. – jxh

4

W standardowym gniazdem API na większości platform, nie ma możliwości odrzucenia połączenia. Musisz połączyć się z numerem accept(), a następnie natychmiast je zamknąć, jeśli nie chcesz.

Wyjątkiem od tej reguły jest funkcja specyficzna dla Winsock WSAAccept(). Zapewnia wywołanie zwrotne, które pozwala aplikacji określić, na podstawie połączenia, czy połączenie powinno zostać zaakceptowane, odrzucone lub przechowywane w kolejce zaległości.

Powiązane problemy