В этой статье представлен принцип и применение протокола websocket в PHP. Подробности заключаются в следующем:
Ниже будет объяснено, что такое websocket и как использовать PHP для реализации websocket.
- Что такое websocket?
- Экземпляр PHP
- Сценарии применения
1. Что такое websocket
Websocket-это своего рода сетевой протокол передачи данных, который может осуществлять полнодуплексную связь по одному TCP-соединению и расположен на прикладном уровне модели OSI. Websocket упрощает обмен данными между клиентом и сервером и позволяет серверу активно передавать данные клиенту.
В API websocket браузеру и серверу достаточно выполнить рукопожатие, чтобы создать постоянное соединение между ними и осуществлять двустороннюю передачу данных.
Особенности: сетевой протокол; двусторонняя передача данных; позволяет серверу активно передавать данные клиенту;
2, Экземпляр PHP
Код клиента index.html
websocket
Серверный код server. php
address = $address; } if(!empty($port)) { $this->port = $port; } } public function service(){ //Get the TCP protocol number. $tcp = getprotobyname("tcp"); $sock = socket_create(AF_INET, SOCK_STREAM, $tcp); socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1); if($sock < 0) { throw new Exception("failed to create socket: ".socket_strerror($sock)."\n"); } socket_bind($sock, $this->address, $this->port); socket_listen($sock, $this->port); echo "listen on $this->address $this->port ... \n"; $this->_sockets = $sock; } public function run(){ $this->service(); $clients[] = $this->_sockets; while (true){ $changes = $clients; $write = NULL; $except = NULL; socket_select($changes, $write, $except, NULL); foreach ($changes as $key => $_sock){ if($this->_ sockets == $_ Socket) {// judge whether it is a new socket if(($newClient = socket_accept($_sock)) === false){ die('failed to accept socket: '.socket_strerror($_sock)."\n"); } $line = trim(socket_read($newClient, 1024)); $this->handshaking($newClient, $line); //Get client IP socket_getpeername ($newClient, $ip); $clients[$ip] = $newClient; echo "Client ip:{$ip} \n"; echo "Client msg:{$line} \n"; } else { socket_recv($_sock, $buffer, 2048, 0); $msg = $this->message($buffer); //Here is the business code echo "{$key} clinet msg:",$msg,"\n"; fwrite(STDOUT, 'Please input a argument:'); $response = trim(fgets(STDIN)); $this->send($_sock, $response); echo "{$key} response to Client:".$response,"\n"; } } } } /** *Handshake handling * @param $newClient socket *Message received by @ return int */ public function handshaking($newClient, $line){ $headers = array(); $lines = preg_split("/\r\n/", $line); foreach($lines as $line) { $line = chop($line); if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) { $headers[$matches[1]] = $matches[2]; } } $secKey = $headers['Sec-WebSocket-Key']; $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "WebSocket-Origin: $this->address\r\n" . "WebSocket-Location: ws://$this->address:$this->port/websocket/websocket\r\n". "Sec-WebSocket-Accept:$secAccept\r\n\r\n"; return socket_write($newClient, $upgrade, strlen($upgrade)); } /** *Analysis of received data * @param $buffer * @return null|string */ public function message($buffer){ $len = $masks = $data = $decoded = null; $len = ord($buffer[1]) & 127; if ($len === 126) { $masks = substr($buffer, 4, 4); $data = substr($buffer, 8); } else if ($len === 127) { $masks = substr($buffer, 10, 4); $data = substr($buffer, 14); } else { $masks = substr($buffer, 2, 4); $data = substr($buffer, 6); } for ($index = 0; $index < strlen($data); $index++) { $decoded .= $data[$index] ^ $masks[$index % 4]; } return $decoded; } /** *Send data *@ param $newclinet new socket *@ param $MSG data to send * @return int|string */ public function send($newClinet, $msg){ $msg = $this->frame($msg); socket_write($newClinet, $msg, strlen($msg)); } public function frame($s) { $a = str_split($s, 125); if (count($a) == 1) { return "\x81" . chr(strlen($a[0])) . $a[0]; } $ns = ""; foreach ($a as $o) { $ns .= "\x81" . chr(strlen($o)) . $o; } return $ns; } /** *Close socket */ public function close(){ return socket_close($this->_sockets); } } $sock = new SocketService(); $sock->run();
Начните с командной строки server.php , а затем откройте его в браузере index.html Он готов к запуску
3, Сценарии применения
- чат-комната
- Толчок в реальном времени
- пулевой чат
- Многопользовательская игра
- Совместное редактирование
- Котировки фондового фонда в режиме реального времени
- Спортивное обновление
- Видеоконференция/чат
- Приложения, основанные на местоположении
- Онлайн-образование
- Умный дом нуждается в высоких сценах в реальном времени
От опроса до websocket
голосование
Между клиентом и сервером все время будет существовать соединение, и время от времени будет выполняться запрос. Клиент будет запрашивать новые сообщения. Таким образом, будет много соединений, одно принимающее и одно отправляющее. Более того, каждый раз, когда отправляется запрос, будет отображаться HTTP-заголовок, который будет потреблять много трафика и загрузки процессора.
Длительный опрос
Длительный опрос-это улучшенная версия опроса. После того, как клиент отправляет HTTP на сервер, новое сообщение не появляется. Если нового сообщения нет, оно будет ждать все время. Только когда клиенту возвращается новое сообщение. В некоторой степени это снижает пропускную способность сети и загрузку процессора. Но у этого метода все еще есть недостаток: например, если скорость обновления данных сервера очень высока, сервер должен дождаться следующего запроса get клиента после отправки пакета данных клиенту, тогда второй обновленный пакет данных может быть доставлен клиенту. Таким образом, самое быстрое время для клиента для отображения данных в реальном времени составляет 2 × RTT (время в оба конца), и если сеть перегружена, пользователи не могут принять это время, например, котировки на фондовом рынке. Кроме того, из-за большого объема данных заголовка HTTP-пакета (обычно более 400 байт), но реальных данных, необходимых серверу, очень мало (иногда всего около 10 байт), такой пакет периодически передается
WebSocket
Теперь острая необходимость заключается в поддержке двусторонней связи между клиентом и сервером, а заголовок протокола не такой большой, как заголовок HTTP, поэтому родился websocket! С точки зрения потребления трафика, то же самое количество опросов клиентов в секунду, когда количество раз достигает десятков тысяч раз в секунду, websocket потребляет всего несколько сотых опроса.
Подробнее о содержании, связанном с PHP, заинтересованные читатели могут ознакомиться с темой сайта: Краткое описание использования сокетов PHP, краткое описание использования строк PHP, краткое описание навыков математических операций PHP, вводный курс объектно-ориентированного программирования PHP, полные навыки работы с массивом PHP, учебник по структуре и алгоритму данных PHP, краткое описание методов расчета программирования PHP и краткое описание навыков сетевого программирования PHP
Я надеюсь, что эта статья будет полезна для программирования на PHP.