2009-08-03 25 views
10

Przeczytałem wzorzec Asio, przeszedł samouczek i przejrzał niektóre przykłady. Nadal nie jestem w stanie zobaczyć, jak gniazdo powinno być zburzone:Jak powinieneś zburzyć boost :: asio :: ip :: udp :: socket?

  1. Czy powinienem wywołać close() czy jest to wykonywane przez destruktor gniazda?
  2. Kiedy należy wywołać wyłączenie()
  3. Jakie są skutki zamknięcia()? Mam świadomość, że "Wyłącza wysyłanie lub odbiór", ale jak to się robi? Czego mogę się spodziewać, jeśli wyślę lub odbiorę gniazdo po wyłączeniu?
  4. Jakie błędy mogę oczekiwać od Close()

Odpowiedz

10

Ponieważ jest to multi-pytanie, zrobię mojej mocy, aby odpowiedzieć na każdą część do swojego zadowolenia:

1) To było moje doświadczenie z gniazdami ASIO, które destruktor obsługuje zamykaniem gniazda. Jednak zajmowałem się tylko gniazdami TCP. Najlepszym sposobem sprawdzenia tego jest po prostu spojrzenie na kod destruktora, aby zobaczyć, czy robi on coś, co przypomina zamknięcie. Wiem, że kod Boost może być trochę trudny do przejścia, więc najprościej byłoby po prostu stworzyć mały przykładowy program, który otwiera gniazdo UDP, a następnie go niszczy. W ten sposób możesz przejść przez kod w debugerze, aby postępować zgodnie z logiką.

Ponieważ projektanci Boost wzięli to pod uwagę dla gniazd TCP, trudno mi sobie wyobrazić, że nie zrobią tego samego dla gniazd UDP.

2) Zadzwoń pod shutdown() tylko wtedy, gdy uważasz, że konieczne jest zapobieganie wykonywaniu przez przyszły kod recv i/lub send na gnieździe. Zazwyczaj nie jest to wymagane, chociaż widziałem, że używa go na gniazdach TCP, aby wymusić od gniazda wysyłanie RST, gdy jest ono zamknięte (w przeciwieństwie do domyślnego "pełnego wdzięku" zamknięcia, gdy przetwarzane są oczekujące wysyłanie).

3) Możesz myśleć o gniazdach jako o dwukanałowej formie komunikacji: jednej do czytania, drugiej do wysyłania. Możesz wyłączyć jeden z nich niezależnie od drugiego i możesz nadal używać jednego kanału, gdy drugi jest wyłączony (tzn. Możesz nadal otrzymywać po zamknięciu dla wysyłania i na odwrót). Zamykanie gniazda jest identyczne jak zamykanie wywołań w przypadku recv i send.

Wyłączanie funkcji recv zapobiega po prostu odczytaniu danych z kodu. Jeśli spróbujesz to zrobić, otrzymasz błąd gniazda. Podobnie, jeśli druga strona połączenia podejmie próbę wysłania danych do ciebie, otrzyma błąd (przepraszam, że ponownie przełączam się do świata TCP, ale uważam, że odpowiedź RST została zwrócona do nadawcy).

Wyłączenie funkcji wysyłania również zapobiega wysyłaniu przez Twój kod dodatkowych danych. Jeśli pamięć obsługuje mnie poprawnie, wygląda to tak samo jak przy zamykaniu gniazda (przesyłany jest pakiet o zerowej długości, aby zasygnalizować drugiej stronie, że dany kanał został zamknięty). Wszelkie przyszłe próby wysłania zwrócą błąd.

4) Musisz sprawdzić swoje dokumenty, aby wiedzieć na pewno. MSDN da ci całkiem niezłą wskazówkę, chociaż nie wiem, czy uważałbym ją za autorytatywną.

+0

Dzięki, zorientowali się trochę tego, ale jestem jeszcze pewien, czy close() naprawdę nazywa się destructor gniazdka za. To, czego tak naprawdę nie zrozumiałem, to ścisły związek między boost asio a tradycyjnym programowaniem sieciowym. Oba wyjaśnienia dotyczące wyłączania() i sugestii sprawdzania kodów błędów gniazda msdn sugerują to. +1 – Torleif

+0

Cieszę się, że mogłem pomóc :) – Brian

+0

FWIW, wywołanie .shutdown (BOTH) na gnieździe UDP działa dla mnie na Windows, ale wieje na Linuksie, ponieważ gniazdo nie jest połączone. –

1

Z przykładów podanych na stronie internetowej Boost wynika, że ​​powinieneś po prostu użyć metody close().Na przykład, spojrzeć na ten jeden:

 
void connection::stop() 
{ 
    socket_.close(); 
} 

Zrobione z tego adresu: HTTP Server

Powiązane problemy