广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >PHP实现WebSocket实例详解
  • 386
分享到

PHP实现WebSocket实例详解

2024-04-02 19:04:59 386人浏览 泡泡鱼
摘要

websocket 是什么? 摘抄网上的一些解释: WEBSocket 协议是基于 tcp 的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务

websocket 是什么?

摘抄网上的一些解释:

WEBSocket 协议是基于 tcp 的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

WebSocket 通信协议于2011年被 IETF 定为标准 RFC 6455,并被 RFC7936 所补充规范。

—— 百度百科

WebSocket 是一个持久化的协议,这是相对于 Http 非持久化来说的。

举个简单的例子,http1.0 的生命周期是以 request 作为界定的,也就是一个 request,一个 response,对于 http 来说,本次 client 与 server 的会话到此结束;而在 http1.1 中,稍微有所改进,即添加了 keep-alive,也就是在一个 http 连接中可以进行多个 request 请求和多个 response 接受操作。然而在实时通信中,并没有多大的作用,http 只能由 client 发起请求,server 才能返回信息,即 server 不能主动向 client 推送信息,无法满足实时通信的要求。而 WebSocket 可以进行持久化连接,即 client 只需进行一次握手,成功后即可持续进行数据通信,值得关注的是 WebSocket 实现 client 与 server 之间全双工通信,即 server 端有数据更新时可以主动推送给 client 端。

上图是一个演示client和server之间建立WebSocket连接时握手部分

client 建立 WebSocket 时向服务器端请求的信息


GET /chat HTTP/1.1 
  Host: server.example.com 
  Upgrade: websocket //告诉服务器现在发送的是WebSocket协议
  Connection: Upgrade 
  Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== //是一个Base64 encode的值,这个是浏览器随机生成的,用于验证服务器端返回数据是否是WebSocket助理
  Sec-WebSocket-Protocol: chat, superchat 
  Sec-WebSocket-Version: 13 
  Origin: http://example.com

服务器获取到 client 请求的信息后,根据 WebSocket 协议对数据进行处理并返回,其中要对 Sec-WebSocket-Key 进行加密等操作


HTTP/1.1 101 Switching Protocols 
  Upgrade: websocket //依然是固定的,告诉客户端即将升级的是Websocket协议,而不是mozillasocket,lurnarsocket或者shitsocket
  Connection: Upgrade 
  Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= //这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key,也就是client要求建立WebSocket验证的凭证
  Sec-WebSocket-Protocol: chat

PHP 服务端


<?php

if(($socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
    echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";
}
if(($ret = socket_bind($socket,'127.0.0.1','9090')) < 0) {
    echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";
}
if(($ret = socket_listen($socket,3)) < 0) {
    echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";
}

$all_sockets = [$socket];    // socket 集合

do {
    $copy_sockets = $all_sockets;   // 单独拷贝一份

    // 因为客户端是长连接,如果客户端非正常断开,服务端会在 socket_accept 阻塞,现在使用 select 非阻塞模式 socket
    if(socket_select($copy_sockets, $write, $except, 0) === false)
        exit('sosket_select error!');

    // 接收第一次 socket 连入,连入后移除服务端 socket
    if(in_array($socket, $copy_sockets)) {
        $client = socket_accept($socket);
        if($client) {
            $buf = socket_read($client, 1024);
            echo $buf;

            // 匹配 Sec-Websocket-Key 标识
            if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/i",$buf,$match)) {
                // 需要将 Sec-WebSocket-Key 值累加字符串,并依次进行 SHA-1 加密和 base64 加密
                $key = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));
                // 拼凑响应内容
                $res= "HTTP/1.1 101 Switching Protocol".PHP_EOL
                    ."Upgrade: WebSocket".PHP_EOL
                    ."Connection: Upgrade".PHP_EOL
                    ."WebSocket-Location: ws://127.0.0.1:9090".PHP_EOL
                    ."Sec-WebSocket-Accept: " . $key .PHP_EOL.PHP_EOL;  // 注意这里,需要两个换行
                // 向客户端应答 Sec-WebSocket-Accept
                socket_write($client, $res, strlen($res));
                // 向客户端发送消息
                socket_write($client, buildMsg('socket ok'), 1024);

                // 加入客户端 socket
                $all_sockets[] = $client;
            }
            // 移除服务端 socket
            $key = array_search($socket, $copy_sockets);
            unset($copy_sockets[$key]);

            // socket_close($client);
        }
    }

    // 循环所有客户端 sockets
    foreach ($copy_sockets as $s) {
        // 获取客户端发给服务端的内容
        $buf = socket_read($s, 8024);
        echo strlen($buf).'---'.PHP_EOL;
        // 代表客户端主动关闭
        if(strlen($buf) < 9) {
            $key = array_search($s, $all_sockets);
            unset($all_sockets[$key]);
            socket_close($s);
            continue;
        }
        // 输出
        echo getMsg($buf).PHP_EOL;
    }

}while(true);
socket_close($socket);

// 编码服务端向客户端发送的内容
function buildMsg($msg) {
    $frame = [];
    $frame[0] = '81';
    $len = strlen($msg);
    if ($len < 126) {
        $frame[1] = $len < 16 ? '0' . dechex($len) : dechex($len);
    } else if ($len < 65025) {
        $s = dechex($len);
        $frame[1] = '7e' . str_repeat('0', 4 - strlen($s)) . $s;
    } else {
        $s = dechex($len);
        $frame[1] = '7f' . str_repeat('0', 16 - strlen($s)) . $s;
    }
    $data = '';
    $l = strlen($msg);
    for ($i = 0; $i < $l; $i++) {
        $data .= dechex(ord($msg{$i}));
    }
    $frame[2] = $data;
    $data = implode('', $frame);
    return pack("H*", $data);
}

// 解析客户端向服务端发送的内容
function getMsg($buffer) {
    $res = '';
    $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++) {
        $res .= $data[$index] ^ $masks[$index % 4];
    }
    return $res;
}

客户端


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        // 创建一个Socket实例
        var socket = new WebSocket('ws://localhost:9090');

        // 打开Socket
        socket.onopen = function(event) {
            // 发送一个初始化消息
            socket.send("init msg");

        };
        socket.onmessage = function(event) {
            console.log('收到消息',event);

        };

        // 监听Socket的关闭
        socket.onclose = function(event) {
            console.log('关闭监听',event);
        };

        function  send()
        {
            socket.send("client msg");
        }
    </script>
</head>
<body>
<button onclick="send()">发送消息</button>
</body>
</html>

运行测试

Client

Server

到此这篇关于PHP实现WebSocket实例详解的文章就介绍到这了,更多相关PHP实现WebSocket内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: PHP实现WebSocket实例详解

本文链接: https://www.lsjlt.com/news/134823.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PHP实现WebSocket实例详解
    WebSocket 是什么? 摘抄网上的一些解释: WebSocket 协议是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务...
    99+
    2022-11-12
  • 详解spring boot实现websocket
    前言QQ这类即时通讯工具多数是以桌面应用的方式存在。在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户端的流量。而websocket的出现,则完...
    99+
    2023-05-31
    spring boot websocket
  • php实现自运行的实例详解
    说明 1、创建一个PHP示例文件;然后输入“ignore_user_abort();”。 2、通过“do{$fp = fopen('test.php','a')...}while(t...
    99+
    2022-11-12
  • Vue websocket封装实现方法详解
    目录1.封装的ws.js文件2.使用方法1.封装的ws.js文件 let global_callback = null let socket = '' // 存储 WebSocket...
    99+
    2022-11-13
  • SpringBoot + WebSocket 实现答题对战匹配机制案例详解
    概要设计 类似竞技问答游戏:用户随机匹配一名对手,双方同时开始答题,直到双方都完成答题,对局结束。基本的逻辑就是这样,如果有其他需求,可以在其基础上进行扩展 明确了这一点,下面介绍开...
    99+
    2022-11-12
  • php 实现websocket服务
    文章目录 前言流程握手 socket_read 读到的报文内容socket_select解析客户端发送的数据客户端发送消息处理前端连接示例完整示例 前言 之前使用的都是封...
    99+
    2023-09-04
    websocket php 网络协议
  • SpringBoot + WebSocket如何实现答题对战匹配机制案例详解
    小编给大家分享一下SpringBoot + WebSocket如何实现答题对战匹配机制案例详解,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!概要设计类似竞技问答游戏:用户随机匹配一名对手,双方同时开始答题,直到双方都完成答...
    99+
    2023-06-15
  • ng+php架构下websocket监听实例
    系统架构:nginx服务器+应用服务器+数据库 通过websocket监听应用服务器的8090端口;前端js发送websocket请求到ng服务器;ng服务器转发请求到应用服务器的8090端口 1、php后端设置websocket监听 $...
    99+
    2023-09-05
    php 架构 websocket
  • SpringBoot+WebSocket实现即时通讯的方法详解
    目录环境信息服务端实现导入依赖创建配置类创建一个注解式的端点并在其中通过配套注解声明回调方法服务端主动发送消息给客户端客户端实现Java客户端实现在前端环境(vue)中使用webso...
    99+
    2022-11-13
  • Java Springboot websocket使用案例详解
    什么是WebSocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 … 为什么要实现握手监控管理 如果说,连接随意创建,不管的话,会存在错误,broken pi...
    99+
    2022-11-12
  • SpringBoot+WebSocket实现多人在线聊天案例实例
    目录1.pom.xml2.消息实体类3.controller4.WebSocket的配置文件5.前端发送消息页面6.测试6.1.客户端A6.2.客户端B1.pom.xml <x...
    99+
    2022-11-13
  • Ratchet实现PHP WebSocket多人聊天功能的示例
       composer 安装ratchet composer require cboden/ratchet 使用PDO连接数据库,创建mysql命令如下 CREATE TABLE messages ( id INT AUTO_INC...
    99+
    2023-08-31
    php websocket 开发语言
  • php memcached的实例用法详解
    1、启动Memcached。 2、使用ps命令查看一下运行状态。 3、创建一个Memcached对象。 4、通过add和get方法添加数据即可。 记得一定要先启动Memcached哦...
    99+
    2022-11-12
  • Redis RESP 协议实现实例详解
    目录引言回顾RESP协议如何拆解RESP协议功能实现总结引言 我们之前已经学习了RESP协议的内容,且已经完成了一个最简单的Redis读写分离中间件,我们来看拆解下该demo, 看看Redis RESP协议实现起来到底有...
    99+
    2022-09-01
  • Redis RESP 协议实现实例详解
    目录引言回顾RESP协议如何拆解RESP协议功能实现总结引言 我们之前已经学习了RESP协议的内容,且已经完成了一个最简单的Redis读写分离中间件,我们来看拆解下该demo, 看看...
    99+
    2022-11-13
  • springboot整合websocket实现群聊思路代码详解
    实现思路 发送者向服务器发送大家早上好。其它客户端可以收到对应消息。 项目展示 通过springboot引入websocket,实现群聊,通过在线websocket测试进行展示。...
    99+
    2022-11-12
  • IOS之WebSocket框架Starscream案例详解
    传统的网络技术 (也就是 Berkeley sockets) 被认为是可靠和稳定的。但是 Berkeley socket 在某些 web 技术,比如代理和防火墙下不太好使。WebSo...
    99+
    2022-05-20
    IOS websocket
  • Spring Boot 实现 WebSocket 的代码示例
    目录什么是 WebSocket ?HTTP vs WebSocket什么时候使用 WebSocket?代码示例1. SpringBoot 使用原生 WebSocket1.1 引入 s...
    99+
    2022-11-13
  • c#实现flv解析详解示例
    下面是一个使用C#实现FLV解析的示例代码:```csharpusing System;using System.IO;public...
    99+
    2023-08-16
    C#
  • redis实现分布式锁实例详解
    目录1、业务场景引入2、基础环境准备2.1.准备库存数据库2.2.创建SpringBoot工程,pom.xml中导入依赖,请注意版本。2.3.application.properti...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作