Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

cURL cz. 3: Zaawansowane funkcje

Interfejs multi

W aplikacjach zbierających dane z wielu źródeł musimy skorzystać w osobnych połączeń do każdego źródła, jakim może być serwer HTTP, FTP czy też POP3. Operacje sieciowe są czasochłonne, a opóźnienia, z jakimi się spotykamy przy nich, mogą wstrzymać działanie aplikacji na dłuższą chwilę. Interfejs curl_multi pozwala nam na zoptymalizowanie tych czynności poprzez zastosowanie gniazdek nieblokujących. Aby nie rozczarować się później, już teraz mogę powiedzieć, że nie służy on do tworzenia krótszego i czytelniejszego kodu. Całe zarządzanie pojedynczymi połączeniami nie może zostać pominięte. Pobieranie danych za jego pomocą jest również trudniejsze, ale myślę, że korzyści ze wzrostu wydajności są znacznie większe.

Gniazdka nieblokujące

Koncepcja transferu asynchronicznego nie jest nowa, lecz warto zdać sobie sprawę z korzyści płynących z wykorzystania tego sposobu przesyłu danych.

Zacznijmy od wyjaśnienia typowej sytuacji, gdy chcemy pobrać dane z dwóch stron na raz. Najprościej pobrać dane kolejno, wykorzystując gniazdka blokujące. Jak sama nazwa wskazuje, gniazdka te blokują wykonanie wątku (w przypadku PHP mówimy o skrypcie) dopóki nie dostaną danych, na które oczekiwały. Po zakończeniu transferu zwracana jest kontrola i możliwe są dalsze operacje. W tym przypadku pobieramy dane z pierwszej strony, a gdy skończymy ściągamy informacje, powtarzamy tę czynność dla drugiej. Prosto policzyć, że jeżeli z pierwszej strony dane będziemy ściągać 2 sekundy, a z drugiej sekundę, to pobranie całości zajmie nam 3 sekundy. Musimy zdać sobie sprawę, że w tych trzech sekundach duża część czasu jest marnowana na opóźnienia występujące w sieciach.

Gniazdka nieblokujące pozwalają nam wykorzystać ten czas na wykonanie operacji na innych połączeniach. Ta sama sytuacja będzie wyglądać teraz nieco inaczej. Po wysłaniu żądania do strony pierwszej oczekujemy na odpowiedź, lecz kontrola jest zwracana do miejsca, w którym zarządzamy połączeniami. Tam sprawdzamy, czy inne gniazdka nie oczekują na wykonanie operacji i ewentualnie pozwalamy im działać. W naszym przypadku zezwalamy wysłać żądanie do drugiej strony. Czekamy w tej chwili na odpowiedzi od obu serwerów, gdyż wszystkie gniazdka oczekują na dane. Okazuje się, że pomimo tego, że pierwsze żądanie zostało wysłane do strony pierwszej, to odpowiedź otrzymaliśmy najpierw z serwera drugiego. Nie musimy czekać na kontynuację operacji pierwszego gniazdka, więc swoją pracę zacznie drugie. Dzięki temu kumulujemy opóźnienia w jednym momencie, co może zaskutkować znacznym przyrostem szybkości działania skryptu.

Jeżeli ten opis nie przemawia do Ciebie, to warto sięgnąć do analogii z życia codziennego. Większość ludzi je rano śniadanie, a większość z nich musi je sama sobie zrobić. Jeżeli chcesz wypić poranną herbatę i zjeść przyzwoite kanapki, musisz poświęcić trochę czasu na przygotowanie ich. Mało błyskotliwa osoba nastawi wodę i zaśnie przy czajniku, budząc się gdy ta zacznie wrzeć. Następnie zaleje herbatę, poczeka aż ta się zaparzy i przejdzie do robienia kanapek. Obdarzeni większym sprytem zrobią to szybciej, nastawiając wpierw wodę na herbatę, a w trakcie oczekiwania wykonają 80% pracy przy kanapkach. Gdy ta zawrze, zaleją herbatę i skończą przygotowywać posiłek, gdy ta się skończy parzyć. Doskonale oddaje to zasadę działania gniazdek nieblokujących – nie czekać bezczynnie.

Przegląd funkcji

curl_multi_init

resource curl_multi_init()

Zwraca nowy uchwyt cURL multi, który wykorzystamy do dodawania połączeń i wykonywania operacji na nich.

curl_multi_close

void curl_multi_close(resource $mh)

Zamyka uchwyt multi.

curl_multi_exec

int curl_multi_exec(resource $mh, int &$still_running)

Obsługuje połączenia dołączone do uchwytu multi. Drugi parametr jest referencją do zmiennej, w której zostanie zapisana liczba wciąż aktywnych połączeń. Funkcję tę musimy wywoływać aż do momentu, gdy wszystkie działania zostaną zakończone. Najważniejsza jest wartość przez nią zwracana, gdyż informuje nas o tym, czy będziemy musieli wywołać ją ponownie. Jeżeli zostanie zwrócona wartość stałej CURLM_OK, to nie ma żadnych pilnych operacji do wykonania. Musimy wtedy sprawdzić, czy instnieją jeszcze aktywne połączenia. Jeżeli nie, to zakończono pobieranie danych. W przeciwnym wypadku musimy wywołać tę funkcję ponownie. Drugą z ważnych wartości zwracanych przez nią jest stała CURLM_CALL_MULTI_PERFORM, która informuje nas o tym, że musimy natychmiast wywołać ponownie funkcję curl_multi_exec.

curl_multi_getcontent

string curl_multi_getcontent(resource $ch)

Zwraca dane pobrane przez określone jedynym parametrem połączenie, jeżeli wartość opcji CURLOPT_RETURNTRANSFER została ustawiona na 1.

curl_multi_add_handle

int curl_multi_add_handle(resource $mh, resource $ch)

Dodaje uchwyt połączenia $ch do uchwytu interfejsu multi $mh. Zwraca zero, gdy wszystko jest w porządku, albo wartość jednej ze stałych CURLM_*.

curl_multi_remove_handle

int curl_multi_remove_handle(resource $mh, resource $ch)

Usuwa połączenie z uchwytu multi.

curl_multi_select

int curl_multi_select(resource $mh [, float $timeout])

Jedna z najprzydatniejszych funkcji. Blokuje wykonanie skryptu do momentu, gdy jedno z gniazdek otrzyma dane. Dzięki temu zmniejszamy znacznie ilość operacji wykonywanych przy obsłudze połączeń. Drugi argument określa czas, po którym nastąpi timeout i zostanie zwrócone zero. Wartością zwracaną jest wartość polecenia systemowego select, czyli liczba gniazdek oczekujących na działanie lub -1 w przypadku błędu.

Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (0)
Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2024 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System