阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

PHP+WebSocket搭建简易聊天室实践

485次阅读
没有评论

共计 4233 个字符,预计需要花费 11 分钟才能阅读完成。

1、前言

公司游戏里面有个简单的聊天室,了解了之后才知道是 node+websocket 做的,想想 php 也来做个简单的聊天室。于是搜集各种资料看文档、找实例自己也写了个简单的聊天室。

http 连接分为短连接和长连接。短连接一般可以用 ajax 实现,长连接就是 websocket。短连接实现起来比较简单,但是太过于消耗资源。websocket 高效不过兼容存在点问题。websocket 是 html5 的资源

本文主要介绍 websocket 简易聊天室的实现步骤具体部分知识点的深入会给出链接或者麻烦读者自己搜集资料。

2、前端

前端实现 websocket 很简单直接

// 连接 websocket

      var ws = new WebSocket(“ws://127.0.0.1:8000”);

// 成功连接 websoc 的时候

ws.onopen = function(){}

// 成功获取服务端输出的消息

ws.onmessage = function(e){}

     // 连接错误的时候
ws.onerror = function(){}

    // 向服务端发送数据

ws.send();

3、后台

    websocket 的难点主要在后台

3.1websocket 连接过程

websocket 通信图解 这是一个简易的客户端和服务端的通信图解,php 主要就做的就是接受加密 key  并返回 其中完成套接字的创建和握手操作

PHP+WebSocket 搭建简易聊天室实践

  下图是一张详细的服务端处理 websocket 的流程图

PHP+WebSocket 搭建简易聊天室实践

   

3.2 代码实践

服务端做的流程大致是:

①、挂起一个 socket 套接字进程等待连接

②、有 socket 连接之后遍历套接字数组

③、没有握手的进行握手操作,如果已经握手则接收数据解析并写入缓冲区进行输出

下面是示例代码(我写的是一个类所以代码是根据函数分段的),文底给出 github 地址以及自己遇到的一些坑

     1、首先是创建套接字

// 建立套接字 
        public function createSocket($address,$port)
        {// 创建一个套接字 
            $socket= socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
            // 设置套接字选项 
            socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
            // 绑定 IP 地址和端口 
            socket_bind($socket,$address,$port);
            // 监听套接字 
            socket_listen($socket);
            return $socket;
        }

  2、将套接字放入数组

public function  __construct($address,$port)
        {// 建立套接字 
            $this->soc=$this->createSocket($address,$port);
            $this->socs=array($this->soc);

        } 

3、挂起进程遍历套接字数组,主要操作都是在这里面完成的

public function run(){// 挂起进程 
            while(true){$arr=$this->socs;
                $write=$except=NULL;
                // 接收套接字数字 监听他们的状态 
                socket_select($arr,$write,$except, NULL);
                // 遍历套接字数组 
                foreach($arr as $k=>$v){// 如果是新建立的套接字返回一个有效的 套接字资源 
                    if($this->soc == $v){$client=socket_accept($this->soc);
                        if($client <0){echo "socket_accept() failed";
                        }else{// array_push($this->socs,$client);
                            // unset($this[]);
                            // 将有效的套接字资源放到套接字数组 
                            $this->socs[]=$client;
                        }
                    }else{// 从已连接的 socket 接收数据  返回的是从 socket 中接收的字节数 
                        $byte=socket_recv($v, $buff,20480, 0);
                        // 如果接收的字节是 0 
                        if($byte<7)
                            continue;
                        // 判断有没有握手没有握手则进行握手, 如果握手了 则进行处理 
                        if(!$this->hand[(int)$client]){// 进行握手操作 
                            $this->hands($client,$buff,$v);
                        }else{// 处理数据操作 
                            $mess=$this->decodeData($buff);
                               // 发送数据 
                            $this->send($mess,$v);
                        }
                    }
                }
            }
        } 

4、进行握手 流程是接收 websocket 内容从 Sec-WebSocket-Key: 中获取 key 并通过加密算法写入缓冲区客户端会进行验证(自动验证不需要我们处理)

public function hands($client,$buff,$v)
        {// 提取 websocket 传的 key 并进行加密(这是固定的握手机制获取 Sec-WebSocket-Key: 里面的 key)
            $buf  = substr($buff,strpos($buff,'Sec-WebSocket-Key:')+18);
            // 去除换行空格字符 
            $key  = trim(substr($buf,0,strpos($buf,"\r\n")));
             // 固定的加密算法 
            $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
            $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
            $new_message .= "Upgrade: websocket\r\n";
            $new_message .= "Sec-WebSocket-Version: 13\r\n";
            $new_message .= "Connection: Upgrade\r\n";
            $new_message .= "Sec-WebSocket-Accept:" . $new_key . "\r\n\r\n";
            // 将套接字写入缓冲区 
            socket_write($v,$new_message,strlen($new_message));
            // socket_write(socket,$upgrade.chr(0), strlen($upgrade.chr(0)));
            // 标记此套接字握手成功 
            $this->hand[(int)$client]=true;
        }

5、解析客户端的数据(我这里没有进行加密,如果有需要也可以自己加密)

// 解析数据 
        public  function  decodeData($buff)
        {//$buff  解析数据帧 
            $mask = array();  
            $data = '';  
            $msg = unpack('H*',$buff);  // 用 unpack 函数从二进制将数据解码 
            $head = substr($msg[1],0,2);  
            if (hexdec($head{1}) === 8) {$data = false;  
            }else if (hexdec($head{1}) === 1){$mask[] = hexdec(substr($msg[1],4,2));  
                $mask[] = hexdec(substr($msg[1],6,2));  
                $mask[] = hexdec(substr($msg[1],8,2));  
                $mask[] = hexdec(substr($msg[1],10,2));  
                   // 遇到的问题  刚连接的时候就发送数据  显示 state connecting
                $s = 12;  
                $e = strlen($msg[1])-2;  
                $n = 0;  
                for ($i=$s; $i<= $e; $i+= 2) {$data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));  
                    $n++;  
                }
                // 发送数据到客户端
                   // 如果长度大于 125 将数据分块 
                   $block=str_split($data,125);
                   $mess=array('mess'=>$block[0],
                       );
                return $mess;                   
            }
PHP+WebSocket 搭建简易聊天室实践

 

6、将套接字写入缓冲区

PHP+WebSocket 搭建简易聊天室实践
// 发送数据 
        public function send($mess,$v)
        {// 遍历套接字数组 成功握手的  进行数据群发 
            foreach ($this->socs as $keys => $values) {// 用系统分配的套接字资源 id 作为用户昵称 
                   $mess['name']="Tourist's socket:{$v}";
                   $str=json_encode($mess);
                   $writes ="\x81".chr(strlen($str)).$str;
                   // ob_flush();
                   // flush();
                   // sleep(3);
                   if($this->hand[(int)$values])
                       socket_write($values,$writes,strlen($writes));
               }
        } 

7、运行方法

github 地址 git@github.com:rsaLive/websocket.git

①最好在控制台运行 server.php

转到 server.php 脚本目录 (可以先 php -v 看下有没有配置 php 如果没有 Linux 配置下 bash windows 配置下 path)

php -f server.php

PHP+WebSocket 搭建简易聊天室实践

如果有错误会提示

PHP+WebSocket 搭建简易聊天室实践

②通过服务器访问 html 文件

PHP+WebSocket 搭建简易聊天室实践

PHP+WebSocket 搭建简易聊天室实践

 

 8、踩过的坑,打开调试工作方便查看错误

server.php 挂起的进程中可以打印输出的,如果出现问题可以在代码中加入打印来调试 

可以在各个判断里面做标记在控制台查看代码运行在哪个区间

不过每次修改完代码之后需要重新运行脚本 php server.php

如果出现这种错误可能是

PHP+WebSocket 搭建简易聊天室实践

1、在与服务器初始套接字的时候发送数据(在第一次与服务器验证握手的时候不能发送内容)

2、如果已经验证过了但是客户端没有发送或者发送的消息为空也会出现这样的情况

所以要检验已连接的套接字的数据

PHP+WebSocket 搭建简易聊天室实践

③可能浏览器不支持或者服务端没有开启 socket 开始之前最好验证下

if (window.WebSocket){console.log("This browser supports WebSocket!");
} else {console.log("This browser does not support WebSocket.");
}

如有不正欢迎指出

 

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计4233字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7984775
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛 NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手! 作为动漫爱好者,你是否还在为...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

  三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Andr...
CSDN,你是老太太喝粥——无齿下流!

CSDN,你是老太太喝粥——无齿下流!

CSDN,你是老太太喝粥——无齿下流! 大家好,我是星哥,今天才思枯竭,不写技术文章了!来吐槽一下 CSDN。...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

  星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定!

星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定!

星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定! 前言 作为 NAS 玩家,你是否总被这些...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...