2012-09-03 8 views
31

PHP ma dwa różne interfejsy API do interakcji z gniazdami. Istnieje interfejs API niskiego poziomu, który zasadniczo owija interfejs API gniazda C. Jest też interfejs API strumieniowego wysokiego poziomu, który implementuje interfejs strumienia PHP.Konwersja zasobu gniazda na gniazdo strumieniowe

Niestety, interfejs API gniazda strumieniowego nie obsługuje ustawiania opcji gniazda niskiego poziomu. Jednak to jest coś, co muszę zrobić. Podobnie gniazdo API nie obsługuje standardowych wywołań funkcji, takich jak fread, fwrite i fclose, co powoduje, że jest on niezgodny z resztą mojego kodu.

PHP 5.4 wprowadziło funkcję socket_import_stream. Umożliwia to pobranie gniazda strumieniowego i uzyskanie podstawowego zasobu gniazda. Mój plan polegał na wykorzystaniu tego do utworzenia gniazda strumieniowego, pobrania gniazda, ustawienia niektórych opcji, a następnie kontynuowania używania oryginalnego gniazda strumieniowego.

Powód, dla którego to nie zadziałało, polega na tym, że muszę ustawić opcje przed wiązaniem. Jedynym sposobem związania gniazda strumienia jest użycie stream_socket_server, które już wykonuje wiązanie. Dlatego nie mogłem go użyć.

Poszukuję teraz odwrotności socket_import_stream, aby przekonwertować zasób gniazda na gniazdo strumieniowe. Nie udało mi się znaleźć takiej funkcji, ale mam nadzieję, że bardzo mądrzy ludzie mogą mi pomóc. Lub prześlij łatkę do źródła PHP, które to robi. Albo podpowiedz mi, jak napisać taką łatkę.

EDYCJA: Mam kod, który działa na strumień PHP do parsowania pakietów DNS z niego. Chcę ponownie użyć tego kodu z gniazdem obsługującym multiemisję. Nie mogę włączyć multiemisji na gnieździe strumieniowym i nie mogę korzystać z funkcji strumieniowych na surowym gnieździe.

EDIT2: Chcę użyć tego strumienia z stream_select, więc niestandardowe obwoluty strumienia nie są opcją, niestety.

+7

Komentarz z kodu źródłowego PHP: 'przytrzymaj referencję do strumienia w strumieniu (przytrzymanie php_stream * może być wykonane bezpośrednio, ale może to być nieco lepsze, jeśli w przyszłości chcemy zapewnić socket_export_stream)' https: // bitbucket.org/php/php-src/src/0ef8b095ccda/ext/sockets/sockets.c#cl-2524 Domyślam się, że 'socket_export_stream' to funkcja, której szukasz, niestety wygląda na to, że jeszcze nie została zaimplementowana. – umpirsky

+3

Przedstawiasz tylko problemy, które napotkałeś, wprowadzając "rozwiązanie" nieopisanego problemu.Rozłóż także oryginalny problem, być może istnieją inne sposoby. –

+0

@ Tiberiu-IonuţStan Dodałem więcej informacji o moim problemie. – igorw

Odpowiedz

6

Możesz użyć funkcji stream_wrapper_register w połączeniu z klasą, która implementuje szablon streamWrapper, aby utworzyć strumień gniazda multiemisji. Umożliwi to wykorzystanie wszystkich wbudowanych funkcji strumienia, ale nie jest tak wygodne, jak socket_export_stream.

+0

To jest właściwe rozwiązanie. Ponieważ tak wiele można zrobić z gniazdem, implementacja opakowania powinna być banalna. – cleong

+0

To trochę pomaga, jednak jest jeden problem z tym rozwiązaniem. Niestandardowe strumienie nie mogą być używane z 'stream_select', ponieważ nie ma sposobu na wyodrębnienie deskryptora pliku. Dodając to teraz do pytania. – igorw

+0

Czy możemy użyć bezpośredniego dostępu do deskryptorów plików, takich jak 'php: // fd/N', aby określić bieżący, który jest nasz? – lisachenko

5

Powód, dla którego to nie zadziałało, polega na tym, że muszę ustawić opcje przed wiązaniem. Jedynym sposobem związania gniazda strumieniowego jest użycie serwera_serwera_tekstowego, który już wykonuje wiązanie. Dlatego nie mogłem go użyć.

4th parametr stream_socket_server() jest $flags, które domyślnie STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, więc nie ommit go dać 0 (lub innego flagi).

Wszakże ustawienie jest zrobione, nadal można ręcznie powiązać (& słuchać), że gniazdo korzystając socket_bind() & socket_listen().

Nie próbowałem, tylko pomysł.

+0

@Ligh Nie jest prawdą, zanotuj '== 0' w drugiej linii, którą połączyłeś. – igorw

+0

@igorw Masz rację, z jakiegoś powodu myślałem, że to faktycznie robi '& ~ STREAM_XPORT_SERVER', aby pobrać oryginalne flagi, i sprawdzając je przed 0, co jest zdefiniowane jako' STREAM_XPORT_CLIENT'. Rzeczywiście, flagi 0 pomijają część wiążącą/nasłuchującą. – Leigh

+0

To był świetny pomysł, ale niestety 'socket_import_stream' próbuje uzyskać rodzinę gniazd, która nie istnieje podczas tworzenia serwera bez flag. Otrzymuję komunikat "Ostrzeżenie: socket_import_stream(): nie można uzyskać rodziny gniazd [9]: Zły deskryptor pliku". – igorw

Powiązane problemy