php基于websocket搭建简易聊天室(socket)

原创 2017年09月13日 13:29:21

前言

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

前端

//连接socket
var ws = new Websocket(‘ws://127.0.0.1:8080’);
//成功连接socket的时候
ws.onopen = function(){}
//成功获取服务端输出的信息
ws.onmessage = function(e){}
//连接错误的时候
ws.onerror = function(){}
//向服务端发送数据
ws.send();

后台,服务端

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

服务端处理websocket的图解

服务端代码

服务端做的流程大致是:
1,挂起一个socket套接字进程等待连接
2,有socket连接之后遍历套接字数组
3,没有握手的进行握手操作,如果已经握手则接收数据解析并写入缓冲区进行输出

套接字

1,将套接字放入数组
public function __contruct($address,$port){
//建立套接字
$this->soc = $this->createSocket($address,$port);
$this->socs = array($this->soc);
}

2,建立套接字
socket_create解释:http://www.php.net/manual/zh/function.socket-create.php
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;
}

挂起进程,遍历套接字数组

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);
        }
     }
    }
   }
}

进行握手

握手流程是接收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;
}

解析客户端的数据

//解析数据
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;
}

将套接字写入缓冲区,发送数据

/发送数据
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));
}
}

GO websocket搭建,https环境

beego 框架搭建websocket聊天室,本地是80端口测试,没有考虑线上https情况,当部署到线上机器,发现https下websocket连接不上,需要进行修改,故进行记录,希望遇到的同学,可...
  • mingzhehaolove
  • mingzhehaolove
  • 2017年02月18日 11:25
  • 2469

【socket】用PHP的socket实现客户端到服务端的通信

一、client.php客户端:
  • yanhui_wei
  • yanhui_wei
  • 2014年08月20日 14:34
  • 34058

基于websocket的简易聊天室的实现

用java实现基于websocket的简易聊天室    WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手...
  • aaa5438438
  • aaa5438438
  • 2016年07月28日 15:32
  • 2493

php基于websocket实现的在线聊天室

本文实例讲述了php基于websocket实现的在线聊天室。分享给大家供大家参考。具体如下: 1、前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想p...
  • zxjiayou1314
  • zxjiayou1314
  • 2017年03月24日 14:44
  • 404

nginx websocket

websocket + nginx配置样例upstream ws_server { ip_hash; server 127.0.0.1:3000; server 127.0.0.1:300...
  • vbaspdelphi
  • vbaspdelphi
  • 2016年12月29日 21:42
  • 439

第17篇 原版更新到合成项目(一)及webrtc一次连通关键点分析

关键词:原版更新到合成项目,webrtc一次连通关键点分析 一、原版更新到合成项目 昨天在原版上解决了连接不稳定问题(即头几次连不上,之后能连上),今天要把原版代码更新到现有项目上。 1.1  更新合...
  • SanBaDao
  • SanBaDao
  • 2016年12月02日 15:05
  • 664

基于Socket的局域网简易聊天室

主要是通过Socket进行编程 Scoket与ServerSocket交互的过程: 1)服务器端程序创建一个ServerSocket,然后调用accept()方法等待客户端进行连接 2)客户端程...
  • zhegemingzihaonan
  • zhegemingzihaonan
  • 2015年09月17日 21:45
  • 1330

发一个WebSocket+PHP聊天室-PHP多进程实时服务器推送技术

这一阵子在家写了个聊天室,给大家献上代码,有用到的可以拿去用。 先介绍下聊天室的特性: 1、服务端采用纯php开发,不依赖php-fpm、nginx、或者apache数据库等,部署简单 2、...
  • u012810515
  • u012810515
  • 2014年04月08日 13:05
  • 9392

PHP资源列表

PHP资源列表 一个PHP资源列表,内容包括:库、框架、模板、安全、代码分析、日志、第三方库、配置工具、Web 工具、书籍、电子书、经典博文等等。 初始翻译信息来自:《推荐!国外程序员整理的 ...
  • u013279509
  • u013279509
  • 2017年11月29日 14:28
  • 149

nodejs如何推送消息到浏览器(socket.io)

了解下 WebSocket 协议及socket.io。nodejs和socket.io是不错的组合,对于不支持 WebSocket 协议的也做了轮询的fallback,使用很简单(来自于socket....
  • z69183787
  • z69183787
  • 2016年09月11日 18:54
  • 2190
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:php基于websocket搭建简易聊天室(socket)
举报原因:
原因补充:

(最多只允许输入30个字)