基于websocket构建简单聊天室的php实践
本文描述了在php中基于websocket构建简单聊天室的实践。分享给大家参考。具体如下:1 .前言
公司游戏里有一个简单的聊天室。了解后知道是节点websocket做的。把php想象成一个简单的聊天室。于是我收集了各种资料,看了文档,找了例子,自己写了一个简单的聊天室。
Http连接分为短连接和长连接。一般短连接可以通过ajax实现,长连接是websocket。短连接实现起来相对简单,但是消耗的资源太多。Websocket是高效的,但是在兼容性上存在一些问题。Websocket是html5的一个资源
2.前端
websocket的前端实现非常简单直接
//connect web socket var ws=new web socket(' ws ://127 . 0 . 0 . 1:8000 ');//ws.onopen=function(){}//() {}当websoc连接成功时//ws . onmessage=function(e){ }//ws . onerror=function(){ }//将数据ws.send()发送到服务器;3.背景
websocket的难点主要在后台
3.1websocket连接过程websocket通信图这是客户端和服务器之间的简单通信图。php主要做的是接受加密密钥并返回它来完成套接字创建和握手操作
下图是服务器端websocket处理的详细流程图
3.2规范实践
服务器进程大致如下:
挂起套接字套接字进程,等待套接字连接被连接,然后遍历套接字数组执行握手而不握手。如果已经执行了握手,则接收数据分析并将其写入缓冲区进行输出。下面是示例代码(我写了一个类,所以代码是按照函数分段的)。文末给出了github地址和我自己遇到的一些坑。1.首先,创建一个套接字。
//创建套接字公共函数create socket ($ address,$ port){//创建套接字$ socket=socket _ create (af _ inet,sock _ stream,sol _ TCP);//设置套接字选项socket _ set _ option ($ socket,sol _ socket,so _ reuseadr,1);//绑定IP地址和端口socket _ bind ($ socket,$ address,$ port);//听socket socket _ listen($ socket);返回$ socket}2.将插座放入阵列中
public function _ _ construct($ address,$ port){//create socket $ this-SOC=$ this-create socket($ 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);//遍历socket数组foreach($arr as $k=$v){ //如果是新建立的socket,返回有效的socket资源if($ this-SOC==$ v){ $ client=socket _ accept($ this-SOC);if($ client 0){ echo ' socket _ accept()失败;}else{ //array_push($this-socs,$ client);//unset($ this[]);//将有效的套接字资源放入套接字数组$ this-socs[]=$ client;} }else{ //从socket接收的字节数是$ byte=socket _ recv ($ v,$ buff,20480,0)。//如果接收到的字节为0,则($byte7)继续;//判断是否有握手,如果没有握手,握手,如果有握手,处理if(!$ this-hands[(int)$ client]){//握手操作$this-hands($client,$buff,$ v);}else{ //处理数据操作$ mess=$ this-decodeData($ buff);//发送数据$this-send($mess,$ v);}}}} }4.握手过程是接收websocket内容,从Sec-WebSocket-Key:获取密钥,通过加密算法写入缓冲区。客户端会验证(自动验证不需要我们处理)
Public function hands ($ client,$ buff,$ v){//提取websocket传递的密钥并加密(这是一种固定的握手机制,用于获取Sec-WebSocket-Key:中的密钥)$ buf=substr ($ buff,strps ($ buff,' Sec-web socket-key 3360 ')//删除换行符空格字符$ key=trim (substr ($ buf,0,strps($ buf ',\ r \ n '));//固定加密算法$ new _ key=base64 _ encode(sha1($ key。258 eafa 5-e914-47da-95ca-c5ab 0dc 85 b 11 ',true));$new_message='HTTP/1.1 101交换协议\ r \ n ';$new_message。=' Upgrade: websocket \ r \ n$new_message。=' Sec-WebSocket-version : 13 \ r \ n ';$new_message。='Connection:升级\ 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.分析客户端的数据(我这里不加密,但如果需要可以自己加密)
//Parse数据公共函数decodedata($ buff){/$ buff Parse数据帧$ mask=array();$ data=$msg=解包(' H* ',$ buff);//使用unpack函数从二进制$head=substr($msg[1],0,2)中解码数据;if(hex dec($ head { 1 })===8){ $ data=false;} else if(hex dec($ head { 1 })===1){ $ mask[]=hex dec(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));//遇到问题刚连接时发送数据,显示连接状态$ 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=数组(' mess'=$block[0],);返回$ mess}6.将套接字写入缓冲区
//发送数据公共函数send ($ mess,$ v){//遍历socket数组并成功握手将数据发送到foreach($ this-socsas $ keys=$ values){//使用系统分配的socket资源id作为用户昵称$ mess[' name ']=' tour ' s socket 3360 { $ v } $ str=JSON _ encode($ mess);$writes='\x81 '。chr(strlen($str))。$ str//ob _ flush();//flush();//睡眠(3);if($ this-hand[(int)$ values])socket _ write($ values,$writes,strlen($ writes));} }7.操作方法
Github地址[电子邮件保护] : rsalive/WebSocket.git。
(1)最好在控制台中运行server.php
转到server.php脚本目录(您可以先检查php是否是由php -v配置的,以及在Linux配置下bash windows配置下是否没有路径)
PHP-f server.php
出现错误时提示
通过服务器访问html文件
8、踩坑,开启调试工作方便查看错误
server.php可以在悬浮过程中打印出来。如果有问题,可以将打印添加到代码中进行调试
您可以在每个判断中做标记,并在控制台中查看代码运行的时间间隔
但是,每次修改代码时,都需要重新运行PHP server.php脚本
(2)如果有这样的错误可能
1.在与服务器的初始套接字上发送数据(您不能在与服务器的第一次身份验证握手时发送内容)
2.如果它已经过验证,但是客户端没有发送它,或者发送的消息是空的,这也会发生
所以检查连接的插座的数据
可能是浏览器不支持或者服务器没有打开套接字。最好在开始之前验证一下
如果(窗口. WebSocket){ console.log('此浏览器支持“WebSocket!”);} else { console.log('此浏览器不支持网络套接字.);}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:基于websocket构建简单聊天室的php实践是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。