PHP имеет два разных API для взаимодействия с сокетами. Существует API-интерфейс сокетов низкого уровня, который в основном обертывает API-интерфейс сокета. И есть API сокетов высокого уровня потока, который реализует интерфейс потока PHP.
К сожалению, API сокета потока не поддерживает настройку параметров гнезда низкого уровня. Однако это то, что я должен сделать. Аналогично, API сокета не поддерживает использование стандартных вызовов функций, таких как fread
, fwrite
и fclose
, что делает его несовместимым с остальной частью моего кода.
В PHP 5.4 была введена функция socket_import_stream . Это позволяет вам взять сокет потока и получить основной ресурс сокета. Мой план состоял в том, чтобы использовать это для создания сокета потока, получить сокет, установить на нем некоторые параметры, а затем продолжить использование исходного сокета потока.
Причина, по которой это не сработало для меня, это то, что мне нужно установить параметры перед привязкой. Единственный способ связать сокет потока – использовать stream_socket_server , который уже выполняет привязку. Вот почему я не мог его использовать.
Теперь я ищу инверсию socket_import_stream
, чтобы я мог преобразовать свой ресурс сокета в сокет потока. Я не смог найти такую функцию, но я надеюсь, что некоторые очень умные люди могут мне помочь. Или подайте патч к источнику PHP, который это делает. Или дайте мне подсказки о написании такого патча.
EDIT: У меня есть код, который действует на поток PHP для анализа DNS-пакетов из него. Я хочу повторно использовать этот код с поддержкой многоадресной рассылки. Я не могу включить многоадресную рассылку в поточном сокете, и я не могу использовать потоковые функции в сыром сокете.
EDIT2: Я хочу использовать этот поток с stream_select
, поэтому пользовательские потоковые обтекатели, к сожалению, не являются опцией.
Вы можете использовать функцию stream_wrapper_register в сочетании с классом, который реализует шаблон streamWrapper для создания потока многоадресной сокеты. Это позволит вам использовать все встроенные функции потока, хотя это не так удобно, как socket_export_stream.
Причина, по которой это не сработало для меня, это то, что мне нужно установить параметры перед привязкой. Единственный способ связать сокет потока – использовать stream_socket_server, который уже выполняет привязку. Вот почему я не мог его использовать.
4-й параметр stream_socket_server()
– это $flags
, по умолчанию – STREAM_SERVER_BIND | STREAM_SERVER_LISTEN
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN
, так что не опускайте его, дайте 0
(или другие флаги).
После того, как все настройки выполнены, вы можете вручную привязать (и прослушать) этот сокет, используя socket_bind()
и socket_listen()
.
Я не пробовал, просто идея.