Ещё один вид транспорта в unix системах, про который я пока не успел ничего рассказать - это сокеты.
В переводе с английского, сокет - это штекер, т.е. элемент, позволяющий соединять между собой всякую фигню, например приборы.
Для лучшего объяснения работы сокетов, удобно использовать популярный в интернете пример с телефоном и телефонной станцией.
Где телефонная станция, словно сервер, держит соединения с сотнями или может тысячами различных телефонных аппаратов, а телефоны, эпизодически устанавливают соединение со станцией, и обмениваются своими данными.
Ровно такая же идея работает и в сокетах, с той лишь разницей что сокет - это интерфейс для доступа к памяти компьтера.
Сокеты подразделяются на два вида:
- “Локальные” или “юникс-сокеты”
- И “веб-сокеты” или ещё их называют “сетевые сокеты”
При этом локальные сокеты видны в файловой системе как файл, но при этом все данные сохраняются в локальной памяти на уровне ядра. А сетевые сокеты биндятся на сетевой порт, и слушают его, являя собой настоящий веб-сервер. (Вы ведь уже придумали что с этим можно сделать, да?)
Понятно, что и создание файла, и бинд порта может делать только один процесс, и его мы обычно называем сервером.
“Сервер” обязан запускаться раньше всех и создавать свой файл или слушать свой порт, повисая в бесконечном цикле.
После чего довольные клиенты должны обращаться к уже созданному файлу и записывать туда (читать оттуда) информацию, или слать невнятные сообщения на сетевой адрес с настоящим IP адресом и портом.
В реализации на php между сетевыми и локальными сокетами разница заметна только в коннекте. Во всём остальном они одинаковы.
Что, уже нетерпится попробовать? Тогда в бой! :-)
simple-server.php
// Создаём сокет, биндим и слушаем
// В случае если мы хотим создать интернет сокет (а мы хотим!)
// Мы должны прописать путь соединения примерно такой
// "tcp://127.0.0.1:8080" что значит мы биндим порт 8080 на локалхосте
$socket = stream_socket_server(
"unix:///tmp/simple-socket",
$errno,
$errstr,
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN
);
if ( ! $socket )
{
echo "$errstr ( $errno )\n";
}
else
{
// Поступающее соединение от клиента принимаем
while ( $conn = stream_socket_accept($socket) )
{
$data = "Московское время" . date("H:i:s") . PHP_EOL;
fwrite( $conn, $data );
fclose( $conn );
}
fclose($socket);
}
simple-client.php
// Тут всё также tcp://127.0.0.1:8080
$socket = stream_socket_client(
"unix:///tmp/simple-socket",
$errno,
$errstr,
30,
STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT
);
if ( ! $socket )
{
echo "$errstr ($errno)\n";
}
else
{
fwrite( $socket, "HI" );
while ( ! feof( $socket ) )
{
echo fgets( $socket, 1024 );
}
fclose( $socket );
}
Мне кажется что примеры слишком простые что бы их как-то комментировать или подробно расписывать.
Поэтому давайте в следующей статье попробуем связать демоны, сокеты, очереди, сигналы и ещё что-нибудь для интереса в одну работающую программу.