PHP 简单实现webSocket
费话少说,用源代码说话
1)客户端实现

1 <html>
2 <head>
3 <meta charset="UTF-8">
4 <title>Web sockets test</title>
5 <script src="jquery-min.js" type="text/javascript"></script>
6 <script type="text/javascript">
7 var ws;
8 function ToggleConnectionClicked() {
9 try {
10 ws = new WebSocket("ws://127.0.0.1:2000");//连接服务器
11 ws.onopen = function(event){alert("已经与服务器建立了连接\r\n当前连接状态:"+this.readyState);};
12 ws.onmessage = function(event){alert("接收到服务器发送的数据:\r\n"+event.data);};
13 ws.onclose = function(event){alert("已经与服务器断开连接\r\n当前连接状态:"+this.readyState);};
14 ws.onerror = function(event){alert("WebSocket异常!");};
15 } catch (ex) {
16 alert(ex.message);
17 }
18 };
19
20 function SendData() {
21 try{
22 var content = document.getElementById("content").value;
23 if(content){
24 ws.send(content);
25 }
26
27 }catch(ex){
28 alert(ex.message);
29 }
30 };
31
32 function seestate(){
33 alert(ws.readyState);
34 }
35
36 </script>
37 </head>
38 <body>
39 <button id='ToggleConnection' type="button" onclick='ToggleConnectionClicked();'>连接服务器</button><br /><br />
40 <textarea id="content" ></textarea>
41 <button id='ToggleConnection' type="button" onclick='SendData();'>发送我的名字:beston</button><br /><br />
42 <button id='ToggleConnection' type="button" onclick='seestate();'>查看状态</button><br /><br />
43
44 </body>
45 </html>

2)服务器端实现

1 class WS {
2 var $master; // 连接 server 的 client
3 var $sockets = array(); // 不同状态的 socket 管理
4 var $handshake = false; // 判断是否握手
5
6 function __construct($address, $port){
7 // 建立一个 socket 套接字
8 $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
9 or die("socket_create() failed");
10 socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1)
11 or die("socket_option() failed");
12 socket_bind($this->master, $address, $port)
13 or die("socket_bind() failed");
14 socket_listen($this->master, 2)
15 or die("socket_listen() failed");
16
17 $this->sockets[] = $this->master;
18
19 // debug
20 echo("Master socket : ".$this->master."\n");
21
22 while(true) {
23 //自动选择来消息的 socket 如果是握手 自动选择主机
24 $write = NULL;
25 $except = NULL;
26 socket_select($this->sockets, $write, $except, NULL);
27
28 foreach ($this->sockets as $socket) {
29 //连接主机的 client
30 if ($socket == $this->master){
31 $client = socket_accept($this->master);
32 if ($client < 0) {
33 // debug
34 echo "socket_accept() failed";
35 continue;
36 } else {
37 //connect($client);
38 array_push($this->sockets, $client);
39 echo "connect client\n";
40 }
41 } else {
42 $bytes = @socket_recv($socket,$buffer,2048,0);
43 print_r($buffer);
44 if($bytes == 0) return;
45 if (!$this->handshake) {
46 // 如果没有握手,先握手回应
47 $this->doHandShake($socket, $buffer);
48 echo "shakeHands\n";
49 } else {
50
51 // 如果已经握手,直接接受数据,并处理
52 $buffer = $this->decode($buffer);
53 //process($socket, $buffer);
54 echo "send file\n";
55 }
56 }
57 }
58 }
59 }
60
61 function dohandshake($socket, $req)
62 {
63 // 获取加密key
64 $acceptKey = $this->encry($req);
65 $upgrade = "HTTP/1.1 101 Switching Protocols\r\n" .
66 "Upgrade: websocket\r\n" .
67 "Connection: Upgrade\r\n" .
68 "Sec-WebSocket-Accept: " . $acceptKey . "\r\n" .
69 "\r\n";
70
71 echo "dohandshake ".$upgrade.chr(0);
72 // 写入socket
73 socket_write($socket,$upgrade.chr(0), strlen($upgrade.chr(0)));
74 // 标记握手已经成功,下次接受数据采用数据帧格式
75 $this->handshake = true;
76 }
77
78
79 function encry($req)
80 {
81 $key = $this->getKey($req);
82 $mask = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
83
84 return base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
85 }
86
87 function getKey($req)
88 {
89 $key = null;
90 if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $req, $match)) {
91 $key = $match[1];
92 }
93 return $key;
94 }
95
96 // 解析数据帧
97 function decode($buffer)
98 {
99 $len = $masks = $data = $decoded = null;
100 $len = ord($buffer[1]) & 127;
101
102 if ($len === 126) {
103 $masks = substr($buffer, 4, 4);
104 $data = substr($buffer, 8);
105 } else if ($len === 127) {
106 $masks = substr($buffer, 10, 4);
107 $data = substr($buffer, 14);
108 } else {
109 $masks = substr($buffer, 2, 4);
110 $data = substr($buffer, 6);
111 }
112 for ($index = 0; $index < strlen($data); $index++) {
113 $decoded .= $data[$index] ^ $masks[$index % 4];
114 }
115 return $decoded;
116 }
117
118 // 返回帧信息处理
119 function frame($s)
120 {
121 $a = str_split($s, 125);
122 if (count($a) == 1) {
123 return "\x81" . chr(strlen($a[0])) . $a[0];
124 }
125 $ns = "";
126 foreach ($a as $o) {
127 $ns .= "\x81" . chr(strlen($o)) . $o;
128 }
129 return $ns;
130 }
131
132 // 返回数据
133 function send($client, $msg)
134 {
135 $msg = $this->frame($msg);
136 socket_write($client, $msg, strlen($msg));
137 }
138 }
测试 $ws = new WS("127.0.0.1",2000);

PHP 简单实现webSocket的更多相关文章
- 用 Go 编写一个简单的 WebSocket 推送服务
用 Go 编写一个简单的 WebSocket 推送服务 本文中代码可以在 github.com/alfred-zhong/wserver 获取. 背景 最近拿到需求要在网页上展示报警信息.以往报警信息 ...
- 【node+小程序+web端】简单的websocket通讯
[node+小程序+web端]简单的websocket通讯 websoket是用来做什么的? 聊天室 消息列表 拼多多 即时通讯,推送, 实时交互 websoket是什么 websocket是一个全新 ...
- springboot搭建一个简单的websocket的实时推送应用
说一下实用springboot搭建一个简单的websocket 的实时推送应用 websocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 我们以前用的http协议只能单 ...
- python简单实现websocket
协议选择的是新的Hybi-10,参考文章如下: http://www.cnblogs.com/zhuweisky/p/3930780.html http://blog.mycolorway.com/2 ...
- 实现一个简单的WebSocket聊天室
WebSocket 简介 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主 ...
- 简单聊聊WebSocket
一.概述 上一篇文章<浅析一次HTTP请求>我们分析了简单的一次 HTTP 请求具体是怎么样完成的,分析了 HTTP 协议的数据结构,如何连接,如何断开,又是如何多路复用的,那么今天我们来 ...
- 用Java构建一个简单的WebSocket聊天项目之新增HTTP接口调度
采用框架 我们整个Demo基本不需要大家花费太多时间,就可以实现以下的功能. 用户token登录校验 自我聊天 点对点聊天 群聊 获取在线用户数与用户标签列表 发送系统通知 首先,我们需要介绍一下我们 ...
- WebSocket简单介绍(WebSocket 实战)(3)
这一节里我们用一个案例来演示怎么使用 WebSocket 构建一个实时的 Web 应用.这是一个简单的实时多人聊天系统,包括客户端和服务端的实现.客户端通过浏览器向聊天服务器发起请求,服务器端解析客户 ...
- WebSocket简单介绍(WebSocket JavaScript 接口)(2)
上一节介绍了 WebSocket 规范,其中主要介绍了 WebSocket 的握手协议.握手协议通常是我们在构建 WebSocket 服务器端的实现和提供浏览器的WebSocket 支持时需要考虑的问 ...
- 使用node+vue实现简单的WebSocket聊天功能
最近学习了一下websocket的即时通信,感觉非常的强大,这里我用node启动了一个服务进行websocket链接,然后再vue的view里面进行了链接,进行通信,废话不多说,直接上代码吧, 首先, ...
随机推荐
- Confluence 6 配置系统属性
在这个页面中描述 Confluence 启动时如何设置 Java 属性和其他选项. 请查看 How to fix out of memory errors by increasing availabl ...
- ubuntu14.04搭建Hadoop2.9.0伪分布式环境
本文主要参考 给力星的博文——Hadoop安装教程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.04 一些准备工作的基本步骤和步骤具体说明本文不再列出,文章中提到的“见参考”均指以上 ...
- jquery二维码生成插件jquery.qrcode.js
插件描述:jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jquery插件 ,使用它可以很方便的在页面上生成二维条码. 转载于:http://www.jq22.com ...
- 八 web爬虫讲解2—urllib库爬虫—ip代理—用户代理和ip代理结合应用
使用IP代理 ProxyHandler()格式化IP,第一个参数,请求目标可能是http或者https,对应设置build_opener()初始化IPinstall_opener()将代理IP设置成全 ...
- maven setting仓库镜像
国内连接maven官方的仓库更新依赖库,网速一般很慢,收集一些国内快速的maven仓库镜像以备用. 最新更新:2016年11月11日 18:05:40 阿里云提供Maven私服,我把配置文件贴一下,自 ...
- 【转】Symstore 详细使用
SymStore (symstore.exe) 是用于创建符号存储的工具.它被包含在Windows调试工具包中. SymStore按照某种格式存储符号,使得调试器可以通过时间戳.映像大小(对于.dbg ...
- 注册表操作的几个windows api
(转自:http://blog.sina.com.cn/s/blog_4e66c6cd01000bcu.html) 键管理类: RegCloseKey():关闭注册表键释放句柄. RegC ...
- 使用ettercap构建arp欺骗构建
0.准备: 安装:ettercap apt-get install cmake libncurses5-dev libssl-dev libpcap-dev libnet1-dev git clone ...
- 查bug受气了,反思
昨天改bug了一天,上午出现bug的原因是Boolean和boolean使用BeanUtils等工具无法自动赋值.我们写的时候注意大小写. 下午查了一个下午没有找到任何原因. 但是我受了气,因为报错点 ...
- WEKA中的数据预处理
数据预处理包括数据的缺失值处理.标准化.规范化和离散化处理. 数据的缺失值处理:weka.filters.unsupervised.attribute.ReplaceMissingValues. 对于 ...