Gniazdo pokrywające się z trybem I/O w porównaniu do trybu blokowania/nieblokowania


Podsumowanie


W tym artykule wyjaśniono różnicę między gniazdem nakładające się atrybut i/O i gniazda blokowania lub tryb nieblokujący.

Więcej informacji


Po utworzeniu gniazda domyślnie jest to gniazdo blokujące. Można użyć polecenia FIONBIO w wywołaniu interfejsu API ioctlsocket, WSAEventSelect, lub WSAAysncSelect aby zmienić tryb gniazda z blokowanie do nieblokujących. Jeśli wywołanie Winsock nie może zakończyć się natychmiast, wywołanie kończy się niepowodzeniem i WSAGetLastError zwraca błąd WSAEWOULDBLOCK, jeśli jest to gniazdo nieblokujące lub bloki wywołań, dopóki operacja zakończy się, jeśli jest to gniazdo blokujące. Gniazdo nakładające się atrybut I/O różni się od trybu blokowania lub nieblokowania gniazda. Chociaż bieżącej implementacji Winsock wymaga nakładające się atrybut I/O dla trybu gniazda nieblokujące, są one koncepcyjnie niezależne i ich model programowania jest inny. Aby utworzyć gniazdo z nakładające się atrybut I/O, można użyć gniazda interfejsu API lub interfejsu API WSASocket z ustawioną flagą WSA_FLAG_OVERLAPPED. Jeśli nakładające się operacji I/O nie można ukończyć natychmiast, wywołanie nie powiedzie się i WSAGetLastError lub GetLastError zwrotu WSA_IO_PENDING lub ERROR_IO_PENDING, który jest faktycznie takie same zdefiniować jako WSA_IO_PENDING. Aby uzyskać dodatkowe informacje, zobacz następujący artykuł z bazy wiedzy Microsoft Knowledge Base:
179942 info: WSA_FLAG_OVERLAPPED jest potrzebny do nieblokujących gniazd
Należy pamiętać, że po utworzeniu gniazda nie ma możliwości zmiany atrybutu nakładające się gniazdo. Jednak można wywołać SetSockOpt interfejsu API z opcją SO_OPENTYPE na dowolne uchwyty gniazda, w tym INVALID_SOCKET, aby zmienić atrybuty nakładające się na wszystkie kolejne wywołania gniazda w tym samym wątku. Domyślna wartość opcji SO_OPENTYPE jest 0, który ustawia nakładające się atrybut. Wszystkie wartości niezerowe opcji sprawiają, że gniazdo synchroniczne i sprawiają, że nie można użyć funkcji uzupełniania. Ustawiając gniazdo na nakładające się atrybut I/O nie oznacza to, że gniazdo będzie wykonywać nakładające się operacji I/O. Na przykład, jeśli określisz NULL dla funkcji uzupełniania i Overlapped struktury w WSARecv i WSASend, lub po prostu wywołać recv lub Send funkcje, zostaną one zakończone w sposób blokowania. Aby upewnić się, że we/wy jest wykonywana w nakładające się mody należy zapewnić nakładające się struktury w funkcji we/wy, w zależności od funkcji, którego używasz.

Nakładające się I/O

W Winsock 1 można utworzyć nakładające się gniazdo przy użyciu gniazda interfejsu API i użyć pliku Win32 API ReadFile, ReadFileEx, WriteFile, WriteFileEx do wykonywania nakładające się we/wy na dojście gniazda. W Winsock 2 można utworzyć nakładające się gniazdo przy użyciu WSASocket z flagą WSA_FLAG_OVERLAPPED lub po prostu za pomocą gniazda interfejsu API. Można użyć powyższych Win32 API I/O plików lub Winsock 2 WSASend, WSASendTo, WSARecv, i WSARecvFrom do inicjowania nakładające się operacji I/O. Jeśli używasz SO_RCVBUF i SO_SNDBUF opcję, aby ustawić zero stosu TCP odbierania i wysyłania buforu, w zasadzie poinstruuj stos TCP bezpośrednio wykonywać we/wy przy użyciu buforu w wywołaniu we/wy. W związku z tym, oprócz zalet nieblokujące nakładające się gniazda we/wy, inne korzyści jest lepszą wydajność, ponieważ zapisać kopię buforu między buforu stosu TCP i buforu użytkownika dla każdego wywołania we/wy. Ale musisz upewnić się, że nie masz dostępu do buforu użytkownika po przesłaniem dla nakładające się operacji i przed zakończeniem nakładające się operacji. Aby ustalić, czy nakładające się operacji I/O została ukończona, można użyć jednej z następujących opcji:
  • Można podać uchwyt zdarzenia w strukturze nakładające się używane w wywołaniu we/wy i poczekaj na dojście zdarzeń do sygnału.
  • Użyj GetOverlappedResult lub WSAGetOverlappedResult do sondowania stanu nakładające się operacji I/O. W systemie Windows NT można określić NULL jako uchwyt zdarzenia w strukturze nakładające się. Jednak w systemie Windows 95 nakładające się struktury musi zawierać uchwyt zdarzenia resetowania ręcznego. WSAGetOverlappedResult w systemie Windows 98 i Windows Millennium Edition (ME) jest modyfikowany tak, że będzie zachowywać się jak Windows NT i może również sondować stan ukończenia z uchwytem zdarzenia NULL w strukturze nakładające się.
  • Użyj ReadFileEx, WriteFileEx, WSARecv, WSARecvFrom, WSASend, lub WSASendTo i wybierz opcję, aby podać funkcję uzupełniania, która ma być wywoływana po zakończeniu nakładające się operacji I/O. Jeśli używasz podejście funkcji uzupełniania, w pewnym momencie po wystawił nakładające się operacji we/wy trzeba wydać Win32 wait funkcji lub wersja WSA wait funkcji oczekiwania na uchwyt nonsignaled umieścić bieżącego wątku w stan oczekiwania alertable. Po zakończeniu nakładające się operacji I/O, funkcja uzupełniania jest wywoływana, funkcja oczekiwania będzie zwracać WAIT_IO_COMPLETION, a wątek oczekiwania alertable budzi się.
  • Użyj GetQueuedCompletionStatus i skojarzyć gniazda, wraz z nakładające się atrybut I/O zestaw z portem zakończenia I/O systemu Windows NT (IOCP). Z IOCP, nie trzeba podać funkcję uzupełniania, poczekaj na uchwyt zdarzenia do sygnału lub sondowania stan nakładające się operacji. Po utworzeniu IOCP i dodać nakładające się uchwyt gniazda do IOCP, można uruchomić nakładające się operacji przy użyciu dowolnego interfejsy API I/O wymienionych powyżej (z wyjątkiem recv, recvfrom, Send, lub SendTo). Będziesz mieć blok wątku roboczego na GetQueuedCompletionStatus API oczekiwanie na pakiet zakończenia we/wy. Po zakończeniu nakładające się I/O, pakiet zakończenia I/O dociera do IOCP i GetQueuedCompletionStatus zwraca. IOCP to system operacyjny Windows NT obsługuje pisanie skalowalnego, wysokiej przepływności serwera przy użyciu bardzo prostego wątków i blokowanie kodu na pokrywające się operacje we/wy. W związku z tym może istnieć znaczne korzyści wydajności przy użyciu nakładające się gniazda I/O z systemu Windows NT IOCPs.

Blokowanie i tryb nieblokujący

Po utworzeniu gniazda domyślnie jest to gniazdo blokujące. W obszarze operacji we/wy gniazda trybu blokowania, Połącz i zaakceptuj operacje wszystkich bloków do momentu zakończenia operacji. Aby zmienić tryb pracy gniazda z trybu blokowania tryb nieblokujący, można użyć WSAAsyncSelect, WSAEventSelect, lub FIONBIO polecenia w wywołaniu interfejsu API ioctlsocket. WSAAsyncSelect mapy gniazda powiadomienia do wiadomości systemu Windows i jest najlepszy model dla pojedynczej aplikacji gwintowanych GUI. WSAEventSelect używa WSAEnumNetworkEvents do określenia charakteru powiadomienia gniazda na zdarzenie sygnalizacji i mapuje gniazda powiadomienia przez sygnalizowanie zdarzenia. Jest to przydatny model dla aplikacji innych niż GUI, które brak pompy komunikatów, takich jak aplikacja usługi systemu Windows NT. Polecenie FIONBIO w wywołaniu interfejsu API ioctlsocket umieszcza gniazda w trybie nieblokującym, jak również. Ale musisz sondować stan gniazda przy użyciu wybierz interfejs API. Aktualizacja: ustawienie SO_RCVBUF na zero z nakładające się recv nie jest konieczne dla systemu Windows 2000, które można bezpośrednio skopiować dane do buforu recv aplikacji. Ustawienie SO_SNDBUF na zero z nakładające się wysyłanie na Windows 2000 nadal ma taką samą korzyść zapisywania kopii jednej pamięci jak na Windows NT 4,0. Ważne jest również, że aplikacja wydaje kilka zaległych nakładające się Send lub recv, jeśli aplikacja ustawia odpowiedni bufor stosu na 0.