10.2. Сокеты
Работающие с сокетами функции передают информацию непосредственно на уровне IP-протокола. Это гораздо более низкий уровень по сравнению с уровнем, на котором работают функция fsockopen и потоки. Многие из них работают с одноименной C-функцией. Для любого имеющего опыт программирования для сокетов на языке C эти функции будут также знакомы. Однако полное обсуждение проблем про­граммирования сокетов выходит за рамки этой книги.
Использование этих функций предполагает решение проблем, неразрешимых с помощью функций более высокого уровня. Другими словами, нет никакого смысла в использовании этих функций для реализации возможностей функции fopen. Они могут пригодиться при таких нетрадиционных применениях PHP, как, например, версия PHP с запуском демона Internet с помощью интерфейса командной строки (command-line interface, CLI).
resource socket_accept(resource socket)
Функция socket_accept предназначена для приема входящего соединения и делает ваш сценарий сервером. Сначала необходимо создать сокет, присвоить ему имя и установить режим прослушивания порта. Функция socket_accept возвращается в режим блокировки только после приема соединения. В незаблокирован-ном режиме она возвращает значение FALSE, когда соединения не ожидают приема. В противном случае будет получен новый ресурс сокета для чтения и записи. В листинге 10.10 продемонстрирован простейший эхо-сервер. После его запуска из командной строки он ожидает соединения клиентов через порт 12345.
Операции ввода-вывода на сетевом уровне
Операции ввода-вывода на сетевом уровне
bool socket_bind(resource socket, string address, integer port)
Функция socket_bind привязывает адрес к ресурсу сокета. Аргумент socket должен быть ресурсом, возвращенным функцией socket_create. Аргумент address должен быть IP-адресом или путем к сокету Unix. Для сокетов Internet необходимо задавать и аргумент port.
socket_clear_error(resource socket)
Эта функция сбрасывает ошибку на указанном сокете или, будучи вызванной без аргументов, на всех сокетах.
socket_close(resource socket)
Функция socket_close закрывает сокет и освобождает память, занятую им.
boolean socket_connect(resource socket, string address, integer port)
Эта функция осуществляет клиентское подключение к порту или сокету. В аргументе socket необходимо указывать сокет, созданный функцией socket_create. С помощью аргумента address задается путь к сокету или IP-адресу. В последнем случае необходимо задавать номер порта.
В листинге 10.11 приводится пример использования сокета UDP для сбора информации о серверах. 
j Листинг 10.11. Функция socket connect_
<?php
// создать UDP- сокет
if(($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))
< 0)
{
print(" Нельзя создать сокет: " .
socket_strerror(socket_last_error()) . "n");
}
// после 5 секунд тайм- аут socket_set_option($socket, SOL_SOCKET,
SO_RCVTIMEO, array('sec'=>5,,usec,=>0)); //подключиться к главному серверу RtCW
if(!socket_connect($socket, wolfmaster.idsoftware.com',
27950))
{
print(" Невозможно подключиться: " .
socket_strerror(socket_last_error()) . "n");
}
// отправить запрос для серверов
socket_write($socket, "xFFxFFxFFxFFgetserversx00"); // получить данные от серверов $server = array();
while(FALSE !== ($line = @socket_read($socket, 4096)))
{
//анализ данных
for($i=22; ($i+5) < strlen($line); $i += 7)
{
$ip = ord(substr($line, $i+1, 1)) . '.' .
ord(substr($line, $i+2, 1)) . '.' .
ord(substr($line, $i+3, 1)) . '.' .
ord(substr($line, $i+4, 1)); $port = (ord(substr($line, $i+5, 1)) * 256) +
ord(substr($line, $i+6, 1)); $server[] = array('ip'=>$ip, 'port'=>$port);
}
}
print("<h1>" . count($server) . " Servers</h1>n"); // просмотр серверов с получением их статуса foreach($server as $s)
{
print("<h1>{$s['ip']}:{$s[,port,]}</h1>n"); // подключиться к серверу RtCW
if(!socket_connect($socket, $s['ip'], $s['port']))
{
print("<p>n" .
socket_strerror(socket_last_error()) .
"n</p>n");
continue;
}
//отправить запрос о статусе
socket_write($socket, "xFFxFFxFFxFFgetstatusx00"); //получить статус сервера
if(FALSE === ($line = @socket_read($socket, 1024)))

print("<p>n" .
socket_strerror(socket_last_error()) .
"n</p>n");
continue;
}
$part = explode("n", $line);
//настройки указаны во второй строке и разделены
//обратной косой чертой
$setting = explode("\", $part[1]);
print("<h2>Настройки</h2> n");
print("<p>n");
for($s=1; $s < count($setting); $s += 2)
{
print("tt{$setting[$s]} = {$setting[$s+1]}<br>n");
}
print("</p>n"); print("<h2>Игроки</h2> n"); $lastPlayer = count($part) - 1; for($p=2; $p < $lastPlayer; $p++)
{
$player = explode(" ", $part[$p]); print("{$player[2]} Score={$player[0]} " . "Ping={$player[1]}<br>n");
}
print("</p>n");
ob_flush();
}
print("</table>n"); socket_close($socket);