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里面进行了链接,进行通信,废话不多说,直接上代码吧, 首先, ...
随机推荐
- 更新增加一个门店ID字段的值
MYSQL因为不能查询一张表时同时更新一张表,同时又会有子查询大于等于一条的情况出现. 分两种情况: 1 直接JOIN 得到一张表. 然后导出做筛选 CREATE TABLE TEST SELECT ...
- laravel利用composer安装
composer create-project laravel/laravel --prefer-dist blog prefer:提升,提拔 dist:距离 blog 创建的项目文件夹名称 lara ...
- YUI笔记 1 模块加载
我们通常开发js程序就是使用<script>标签把脚本引入到页面中进行开发,如果是简单的逻辑还好,但是如果是比较庞大的大规模js开发,可能会出现下面的问题: 1. <script& ...
- 【python】类file文件处理
[flush方法] 通常由于缓冲,write不将数据写入文件,而是写入内存的缓冲区,需要使用flush写入文件,并清空缓冲区 文件的flush方法的作用是强制清空缓存写入文件.默认每行flush一下? ...
- 用函数式编程,从0开发3D引擎和编辑器(一)
介绍 大家好,欢迎你踏上3D编程之旅- 本系列的素材来自我们的产品:Wonder-WebGL 3D引擎和编辑器 的整个开发过程,探讨了在从0开始构建3D引擎和编辑器的过程中,每一个重要的功能点.设计方 ...
- (二)js选择结构
1.js的执行顺序. a) 一般按照书写的顺序来执行. b) 另外一种是通过判断然后执行下一项语句. 注:一般讲js语句写在body内容的最后来执行. 2.js的结构 a) 顺序结构 ...
- Java [Leetcode 357]Count Numbers with Unique Digits
题目描述: Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. ...
- 【转载】Python正则表达式指南
本文转自:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html#!comments 1. 正则表达式基础 1.1. 简单介绍 正则表达 ...
- Elasticsearch.net项目
Elasticsearch.net项目实战 https://www.cnblogs.com/lucky_hu/p/9746736.html elasticsearch.net项目实战 @智客幸达 目录 ...
- 洛谷 P3015 [USACO11FEB]最好的括号Best Parenthesis
传送门 题目大意:给出括号的得分标准. ()得分为1,如果A的得分为S(A),那么 (A)的得分为2*S(A). 题解:搜索 #include<iostream> #include< ...