Simple Web-Socket Client

Для чего нужны веб-сокеты

Веб-сокеты (1) — это технология, позволяющая устанавливать непрерывное соединение между клиентом и сервером. Особенность такой системы также в том, что сервер может по своей инициативе отправлять данные одному или нескольким клиентам. Это позволяет создавать real-time мессенджеры, онлайн-игры и прочие проекты.

PHP, казалось бы, не подходит для такой цели. Он обычно используется для создания динамических веб-страниц и работает по принципу «открыл-ответил-закрыл». Что же, стереотипы пора ломать…

Пример работы с веб-сокетами

см. в (1) пример библиотеки по вебсокетам:

Данный класс избавляет вас от необходимости скачивания сторонних демонов или написания сервера самостоятельно. Всё, что вам потребуется — подключить класс и написать функции приёма сообщений, при желании ещё и heartbeat. Чтобы использовать класс, просто включите его в ваш скрипт

В (2) см. пример работы с сокетами — реализация чата.

Будем изучать простейший пример по мануалу (3), скачав исходники (4):

Проверка поддержки сокетов на хостинге

– Что нужно сделать в первую очередь для начала работы с WebSocket?

– Проверить поддержку сокетов на хостинге и в Денвере.

Для этого создаём простенький файлик sockettest.php

php sockettest.php WebSockets UNAVAILABLE

Исходники

      

http://socket.js Server address:

Message:

   

Messages from web-socket:
"use strict"; (function () < // private vars var socket; //////////////////////////////////////////////////////////////////////////// var init = function () < socket = new WebSocket(document.getElementById("sock-addr").value); socket.onopen = connectionOpen; socket.onmessage = messageReceived; socket.onerror = errorOccurred; /** * Send button click */ document.getElementById("sock-send-butt").onclick = function () < socket.send(document.getElementById("sock-msg").value); >; /* * Disconnect button click */ document.getElementById("sock-disc-butt").onclick = function () < connectionClose(); >; /** * Reconnect button click */ document.getElementById("sock-recon-butt").onclick = function () < socket = new WebSocket(document.getElementById("sock-addr").value); socket.onopen = connectionOpen; socket.onmessage = messageReceived; >; >; // open socket connection function connectionOpen() < socket.send("Connection with "" + document.getElementById("sock-addr").value + "" Connection SUCCESS."); >// get message function messageReceived(e) < console.log("Server response: " + e.data); document.getElementById("sock-info").innerHTML += ("Message: " + e.data + "
"); > // error message function errorOccurred(e) < console.log("Server error: " + e.data); document.getElementById("sock-info").innerHTML += ("Error: " + e.data + "
"); > // close socket connection function connectionClose() < socket.close(); document.getElementById("sock-info").innerHTML += "Connection closed
"; > return < // ---- onload event ---- load: function () < window.addEventListener('load', function () < init(); >, false); > > >)().load();
rn"; echo "socket_create . "; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$socket) < echo "Error: " . socket_strerror(socket_last_error()) . "
rn"; exit(); > else < echo "OK
rn"; > echo "socket_bind . "; // привязываем его к указанным ip и порту // !! если возникает ошибка коннекта, меняет тут порт на любой другой $bind = @socket_bind($socket, '127.0.0.1', 8890); if (!$bind) < echo "Error: " . socket_strerror(socket_last_error()) . "
rn"; exit(); > else < echo "OK
rn"; > // разрешаем использовать один порт для нескольких соединений socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); echo "Listening socket. "; $listen = socket_listen($socket, 5); // слушаем сокет if (!$listen) < echo "Error: " . socket_strerror(socket_last_error()) . "
rn"; exit(); > else < echo "OK
rn"; > // Бесконечный цикл ожидания подключений while (true) < echo "Waiting. "; // Зависаем пока не получим ответа $accept = @socket_accept($socket); if ($accept === false) < echo "Error: " . socket_strerror(socket_last_error()) . "
rn"; usleep(100); > else < echo "OK
rn"; echo "Client "" . $accept . "" has connected
rn"; > $msg = "Hello, Client!"; echo "Send to client "" . $msg . "". "; socket_write($accept, $msg); echo "OK
rn"; if ((round(microtime(true), 2) - $starttime) > 100) < echo "time = " . (round(microtime(true), 2) - $starttime); echo "EXIT.
rn"; return $socket; > sleep(10); // засыпаем на 10 сек > > error_reporting(E_ALL); // Выводим все ошибки и предупреждения set_time_limit(0); // Время выполнения скрипта не ограничено ob_implicit_flush(); // Включаем вывод без буферизации $socket = go(); // Функция с бесконечным циклом, возвращает $socket по запросу выполненному по прошествии 100 секнуд. echo "go() ended
rn"; if (isset($socket)) < echo "Closing connection. "; @socket_shutdown($socket); socket_close($socket); echo "OK
rn"; >

Тестируем

Шлем сообщения и получаем их тут же:

Во вкладке клиента в поле Server address вводим ws://127.0.0.1:889 и нажимаем reconnect, мы видим что на клиенте ничего не происходит:

а на сервере появляются сообщения вида:

Чтобы окончательно убедиться в том, что сервер отвечает, что его сообщения не блокируются файрволом, запустите скрипт сервера http://exp/websockets/simpleworking.php запустите telnet и попытайтесь подключиться к 127.0.0.1:889, только это нужно сделать не позднее 100 секунд, с момента запуска сервера, пока он не закрыл соединения и не завершил скрипт.

По telnet должен придти ответ “Hello, Client!”, что свидетельствует о том, что всё работает в штатном режиме и связь с сервером двухсторонняя.

Фиксим ошибки

У меня выдается ошибка при коннекте:

также теперь ошибка коннкета в клиенте:

Все сообщения отправляемые по протоколу WebSocket можно разделить на несколько видов: handsnake (рукопожатие при установлении связи), ping-pong(проверка связи) и data-transfer(передача данных). Также есть более краткое описание протокола в общих чертах на русском в (5)

Fix: меняем порт в simpleworking.php:

Теперь вроде работает, сервер получает сообщения:

C этим разобрались , можно еще изучить расширенный урок по демонам в (6)

Источник

Javascript клиент сервер php

БлогNot. Привязываем к клиенту Javascript серверную часть на PHP

Привязываем к клиенту Javascript серверную часть на PHP

Мне понадобилось в учебных целях (и пока без JQuery) продемонстрировать, как можно для клиентского скрипта, например, некой игры, написанной на HTML+Javascript, поддерживать с помощью серверного скрипта на PHP некий общий для всех файл (например, таблицу лучших игроков).

  • реализовать отправку данных от клиентского скрипта серверному, который отвечает за сохранение общей для всех таблицы результатов;
  • хранить в обычном текстовом файле небольшое фиксированное число записей вида «счёт-имя-дата/время» (базу пока тоже не используем);
  • максимально просто и хотя бы минимально безопасно обновлять данные по запросу из клиента;
  • серверный скрипт должен уметь сообщать клиентскому результаты своей работы, то есть, по выполнении кода, редиректить обратно на страницу клиента, при этом клиентский скрипт показывает, что сделал серверный.

Саму «игру» возьмём простейшей, кто больше раз нажмёт кнопку, тот и прав. А раз можно только тупо кликать, пусть «Кликушей» продукт и называется.

Вот код клиентского скрипта и комментарии к нему:

  

Рекомендуется в заголовке HTML-документа со скриптом поставить вот такие мета-теги:

Метод alltrim убирает из строки-параметра как лишние пробелы между словами, так и лишние лидирующие или завершающие пробелы.

Метод getname() позволяет ввести имя пользователя или оставить его без изменений. Рекомендуется всегда использовать имя по умолчанию. Как-то я видел «бесконечный» ввод имени, то есть, примерно вот такую getname() :

function getname () < var input=false; var name=''; while (input==false) < name = prompt("Пожалуйста, введите Ваше имя:", "Гость"); if (name!=null && alltrim(name)!='') input=true; >return alltrim(name); >

Делать так, по-моему, некорректно — во первых, при повторном выводе окна запроса в современных браузерах пользователь может отметить флажок «Предотвратить создание дополнительных диалоговых окон на этой странице», во-вторых, если он не хочет ничего вводить или стёр имя по умолчанию, пусть так и остаётся гостем.

Метод getparam() — пример того, как на Javascript обработать параметры, переданные странице методом GET (через URL-адрес). Возвращает объект, а не просто массив, то есть, при вызове

Методы click1() и click2() понадобились потому, что стандартная кнопка отправки данных в HTML игнорирует другие кнопочные элементы, так что мы не смогли бы передать число от кнопки с цифрой.

Можно было попробовать отправлять результат и так:

принимая его в серверном скрипте методом GET , но это может быть запрещено, например, модулем Анти-баннер антивируса Касперского.

Основные действия серверного скрипта подробно закомментированы:

      '; > //Подвал страницы на HTML: function end1 () < echo ''; exit (2); > //Функция для сравнения 2 записей файла function compare ($a,$b) < //счёт-имя-дата/время @list ($ca,$na,$da) = explode ($GLOBALS['key'], $a); @list ($cb,$nb,$db) = explode ($GLOBALS['key'], $b); if (intval($ca)>intval($cb)) return 1; else if (intval($ca)intval($db)) return 1; else if (intval($da) > $status = 1; //Статус, который вернём клиенту; 1=ошибка //Читаем и вносим в массив $a список из файла: $table = @file_get_contents ($GLOBALS['filename']); $a = explode("\n", $table, $GLOBALS['limit']); if (isset($_GET['a'])) < //Если это был запрос "Показать список" start1(); if (count($a)Список лучших пока пуст, станьте первым

'; > else < echo ''."\n". ''; for ($i=0; $i'; > echo '
ИмяРезультатДата
'.$name.''.$result.''.date("d.m.Y, H:i",$date).'
'."\n"; > end1(); > else if (isset($_POST['name']) and isset($_POST['cnt'])) < //Если это был запрос на внесение данных $name = htmlspecialchars(alltrim($_POST['name'])); //Получить имя $cnt = intval(htmlspecialchars(alltrim($_POST['cnt']))); //. и счёт игрока if ($cnt>0) < //Если счёт не пуст, $time = time(); //получить метку времени, $key = $GLOBALS['key']; //разделитель записей, $item = "$cnt$key$name$key$time"; //сформировать строку с новой записью, array_push ($a, $item); //сунуть её в массив, $a = array_unique($a); //на всякий случай, убить одинаковые элементы в массиве, if (count($a)>1) uasort ($a,'compare'); //отсортировать записи собственной функцией, $a = array_slice(array_reverse ($a),0,$GLOBALS['limit']); //перевернуть массив (по убыванию счёта) и избавиться от лишних записей $data = implode ("\n",$a); //положить данные в строку $data $status = (in_array($item,$a)==true?0:1); //новый элемент в массиве? Если да, статус=0 (успех) if ($status==0) < $res = @file_put_contents ($GLOBALS['filename'],$data,LOCK_EX); //монопольно записать в файл if ($res === false) $status = 2; //НЕ удалось записать - увы, вернём ошибку :) >> > header('Location: index.html?status='.$status.'&name='.$name); //Вернём клиенту его имя и статус ?>

Следует помнить, что для более безопасной работы с данными существуют базы, а сделать всё с меньшими усилиями в наше время можно с помощью библиотеки JQuery.

26.09.2014, 13:23 [12206 просмотров]

Источник

Читайте также:  Php ini upload files
Оцените статью