2009-09-16 14 views

Odpowiedz

18

Tak, to jest to, do czego służy socket_set_nonblock(). Twój kod interakcji z gniazdem musi być napisany inaczej, biorąc pod uwagę specjalne znaczenia kodów błędów 11, EWOULDBLOCK i 115, EINPROGRESS, załóżmy.

Oto niektóre nieco-fabularyzowany przykładowy kod z pętli gniazdo odpytywania PHP synchronizacji, na wniosek:

$buf = ''; 
$done = false; 
do { 
    $chunk = socket_read($sock, 4096); 
    if($chunk === false) { 
     $error = socket_last_error($sock); 
     if($error != 11 && $error != 115) { 
      my_error_handler(socket_strerror($error), $error); 
      $done = true; 
     } 
     break; 
    } elseif($chunk == '') { 
     $done = true; 
     break; 
    } else { 
     $buf .= $chunk; 
    } 
} while(true); 
+0

Co masz na myśli inaczej? Czy możesz pokazać mi jakieś próbki kodu zdarzeń asynchronicznych odebranych? –

+0

To jest synchroniczne, ale nie blokujące? Co dokładnie oznacza brak blokowania? –

+3

Nie, jest to asynchroniczne i oparte na odpytywaniu. Kod pochodzi z większego mechanizmu odpytywania. PHP nie ma wsparcia dla zdarzeń wejścia/wyjścia gniazda sterowanego przerwaniami/sygnałami, o ile wiem, o co prosisz. Osiągasz asynchroniczną komunikację za pomocą operacji, które nie czekają na zakończenie, ale natychmiast powracają z indykatywnym kodem błędu, jeśli operacja nie jest gotowa. Jak czyta na nieblokującym gnieździe. Istnieje wiele samouczków na temat użycia asynchronicznego gniazda w C, które będą zawierały wiele szczegółów; Wsparcie PHP to tylko warstwa ponad standardowymi materiałami C. – chaos

0

AFAIK PHP jest ściśle singlethreaded, co oznacza, że ​​nie może tego zrobić asynchronicznie, ponieważ wykonanie skryptu jest zawsze liniowy.

Minęło trochę czasu, odkąd to zrobiłem, ale o ile sobie przypominam, można otworzyć tylko gniazdo, a skrypt powinien kontynuować wykonywanie po otrzymaniu danych.

+0

Nawet próbka kodu chaosu zdaje się potwierdzać ten fakt. –

+1

PHP udostępnia funkcję stream_select dla operacji asynchronicznych, analogicznie do posix select(). – karunski

+1

select() jest synchroniczna: pozwala po prostu dowiedzieć się, czy gniazdo jest gotowe do odczytu/zapisu. Nadal wywołujesz go z jednego wątku i blokujesz wywołanie select() zamiast read() lub write(). –

5

Jak zrobić to samo asynchronicznie? więc mogę odpowiedzieć na dane w przypadku danych otrzymał zamiast odpytywania dla danych itp

Trzeba będzie wykonać skrypt i wydawać stream_select sprawdzić weither nie ma żadnych danych do odbioru. Przetwórz i wyślij dane z powrotem.

5

Termin "asynchroniczny" jest często nadużywany w programowaniu sieciowym. W przypadku operacji we/wy asynchroniczne często są po prostu używane jako inne słowo nie blokujące. Oznacza to, że proces może być kontynuowany przed zakończeniem transmisji w api sieci.

Dla realizacji procesu w ogół asynchroniczny oznacza wielokrotne instrukcje mogą być obliczane jednocześnie (równolegle).

Innymi słowy, asynchroniczny I/O nie jest prawdziwie asynchroniczne o ile kilka nici są stosowane w celu umożliwienia wielokrotnego czyta/zapisuje/akceptuje, aby wystąpiły jednocześnie - wszystkie gniazda będą musiały czekać na synchroniczne wywołanie nieblokujące, jeśli ma dane do odczytu/zapisu lub nie będzie blokować, a odczyt/zapis dużego pliku może nadal zająć sekundy lub nawet minuty, jeśli nie zostanie przerwany. Należy zauważyć, że wymagałoby to doskonałego przepływu między klientem a serwerem lub sam TCP przerwie transmisję. Na przykład serwer wysyłający szybciej niż klient może pobrać, spowoduje blokowanie zapisu.

Z ścisłego punktu widzenia PHP nie może wykonywać asynchronicznych połączeń sieciowych, a jedynie blokować. W skrócie, postęp procesu zatrzyma się, gdy połączenie sieciowe będzie w stanie z pożytkiem odczytywać/zapisywać itd. Jednak proces będzie kontynuowany, gdy wywołanie nie będzie w stanie z pożytkiem odczytać/zapisać lub w przeciwnym razie zablokować. W prawdziwie asynchronicznym systemie proces będzie kontynuowany niezależnie, a odczyt/zapis zostanie wykonany w innym wątku. Zauważ, że blokowanie operacji we/wy może być wykonane asynchronicznie, jeśli zostanie wykonane w innym wątku.

Co więcej, PHP nie jest w stanie wykonywać sterowanych przez zdarzenia operacji we/wy bez instalowania rozszerzenia, które je obsługuje. W przeciwnym razie musisz wykonać jakąś formę odpytywania, aby wykonać nieblokujące operacje we/wy w PHP. Kod z Chaos byłby funkcjonalnym nieblokującym odczytanym przykładem, gdyby używał socket_select.

Przy tym powiedziane, funkcja select nadal zezwala na zachowanie nie blokujące w PHP. W języku C usługi odpytywania mają utratę wydajności w stosunku do zdarzeń, więc jestem pewien, że byłoby to takie samo w przypadku PHP. Ale ta strata jest w nanosekundach-mikrosekundach w zależności od ilości gniazd, gdzie czas zaoszczędzony od połączenia nie blokującego to zwykle milisekundy, a nawet sekundy, jeśli połączenie ma czekać.

Powiązane problemy