Swoole实现基于websocket的webIM聊天室 | Heimo's blog


本站和网页 https://heimo-he.github.io/2018/03/30/php-swoole-webim/ 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

Swoole实现基于websocket的webIM聊天室 | Heimo's blog
Heimo's blog
首页
分类
标签
归档
搜索
Swoole实现基于websocket的webIM聊天室
发表于
2018-03-30
阅读次数
这是一个简单的基于php Swoole扩展实现的聊天室demo。
本文源码github地址
前言-浅析websocket
什么是websocket
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
为什么会有websocket
长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTTP轮询的滥用: 客户端向主机不断发送不同的HTTP呼叫来进行询问。
这会导致一系列的问题:
1.服务器被迫为每个客户端使用许多不同的底层TCP连接:一个用于向客户端发送信息,其它用于接收每个传入消息。
2.有线协议有很高的开销,每一个客户端和服务器之间都有HTTP头。
3.客户端脚本被迫维护从传出连接到传入连接的映射来追踪回复。
一个更简单的解决方案是使用单个TCP连接双向通信。 这就是WebSocket协议所提供的功能。 结合WebSocket API ,WebSocket协议提供了一个用来替代HTTP轮询实现网页到远程主机的双向通信的方法。
WebSocket协议被设计来取代用HTTP作为传输层的双向通讯技术,这些技术只能牺牲效率和可依赖性其中一方来提高另一方,因为HTTP最初的目的不是为了双向通讯。
名称的由来
08年6月18日,一群WHATWG的工程师在讨论一些技术问题,一个工程师提到说「我们之前讨论的那个东西,不要叫TCPConnection 了,还是起个别的名字吧 」,接着几个名字被提及,DuplexConnection,TCPSocket,SocketConnection 。
Socket一直以来都被人用来表示网络中一个连接的两端,考虑到怎么让工程师更容易接受,后来Hixie提出了WebSocket ,大家都没有异议,紧接着mcarter在Comet Daily中发表了文章Independence Day: HTML5 WebSocket Liberates Comet From Hacks,后来随着各大浏览器对WebSocket的支持,它变成了实际的标准,IETF也沿用了这个名字。
接口定义
WHATWG文档中对WebSocket接口的定义
协议基础
WebSocket的目的是取代HTTP在双向通信场景下的使用,而且它的实现方式有些也是基于HTTP的(WS的默认端口是80,WSS是443)。现有的网络环境(客户端、服务器、网络中间人、代理等)对HTTP都有很好的支持,所以这样做可以充分利用现有的HTTP的基础设施,有点向下兼容的意味。
和http的关系(握手)
浏览器请求
GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://服务器地址
Sec-WebSocket-Version: 13
服务器回应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
WebSocket借用http请求进行握手,相比正常的http请求,多了一些内容。其中,
Upgrade: websocket
Connection: Upgrade
表示希望将http协议升级到Websocket协议。
Sec-WebSocket-Key是浏览器随机生成的base64 encode的值,用来询问服务器是否是支持WebSocket。
服务器返回
Upgrade: websocket
Connection: Upgrade
告诉浏览器即将升级的是Websocket协议
Sec-WebSocket-Accept是将请求包“Sec-WebSocket-Key”的值,与”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″这个字符串进行拼接,然后对拼接后的字符串进行sha-1运算,再进行base64编码得到的。用来说明自己是WebSocket助理服务器。
Sec-WebSocket-Version是WebSocket协议版本号。RFC6455要求使用的版本是13,之前草案的版本均应当被弃用。
更多握手规范详见RFC6455。
和socket的关系
就像Java和JavaScript,并没有什么太大的关系,但又不能说完全没关系。可以这么说:
1.命名方面,Socket是一个深入人心的概念,WebSocket借用了这一概念;
2.使用方面,完全两个东西。
环境准备
安装swoole
1pecl install swoole
准备好jQuery.js
websocket_server.php
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
/**
* Created by PhpStorm.
* User: heimo
* Date: 2017/6/8
* Time: 下午10:52
*/
/*
创建wss
$ws = new swoole_websocket_server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$ws->set(array(
'ssl_cert_file' => '/ssl/xxxx.crt',
'ssl_key_file' => '/ssl/xxxx.key',
));
*/
//创建websocket服务器对象,监听0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);
//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
//var_dump($ws);
//var_dump($request);
echo "client-{$request->fd} is connected\n";
});
//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
echo "client-{$frame->fd} send message:".$frame->data."\n";
foreach($ws->connections as $fd)
echo "push message to client-{$fd} \n";
$ws->push($fd, $frame->data);
});
//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
chat.html
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket</title>
</head>
<style>
.sendBox { margin: 15px; }
.sendBox .input { width: 200px;height: 25px; }
.sendBox .button{ width: 60px;height: 25px; }
</style>
<body>
<div class="sendBox">
<input class="input" id="msg" />
<button class="button" type="button" onclick="send()">send</button>
</div>
<hr>
<div>
<ul id="chatMsg">
</ul>
</div>
</body>
<script type="text/javascript" src="jquery.js"></script>
<script>
var wsServer = 'ws://websocket_server_ip:9502';
var websocket = new WebSocket(wsServer);
//打开事件
websocket.onopen = function (evt) {
$("#chatMsg").append("<li style='color: green'>Connected to WebSocket server!</li>");
};
//关闭事件
websocket.onclose = function (evt) {
$("#chatMsg").append("<li style='color: red'>Disconnected!</li>");
};
//消息事件
websocket.onmessage = function (evt) {
$("#chatMsg").prepend("<li style='color: blue'>new message:"+escapeHtml(evt.data)+"</li>");
};
//异常事件
websocket.onerror = function (evt, e) {
$("#chatMsg").append("<li style='color: red'>Error occured:"+evt.data+"</li>");
};
//发送消息
function send() {
var msg = $('#msg').val();
if (msg.length/1024 > 1 || msg.length == 0){
alert('消息内容不符合规范');
}else {
websocket.send(msg);
$('#msg').val('');
document.onkeydown = function(e){
var ev = document.all ? window.event : e;
if(ev.keyCode==13) {
send();
$('#msg').val('');
//过滤
var entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
function escapeHtml(string) {
return String(string).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
</script>
</html>
启动服务
修改chat.html中wsServer的配置为自己的配置
1 var wsServer = 'ws://websocket_server_ip:9502';
配置Nginx使用户能够访问到chat.html
启动websocket_server
php websocket_server.php
访问页面
浏览器打开chat.html
构建整个IM需要考虑的问题
安全问题
1.身份认证:token
2.防止越权:代码逻辑
3.XSS:过滤
4.https和wss
性能问题
1.并发
2.异步
稳定性
1.心跳:服务端
2.断线重连:客户端
转载使用注明出处。原文链接 https://heimo-he.github.io/2018/03/30/php-swoole-webim/
# swoole
# php
# websocket
shadowsocks2.8.2EVP_CIPHER_CTX_cleanup错误
PHP打开OPcache
文章目录
站点概览
Heimo
玫瑰即玫瑰,花香无意义
34
日志
11
分类
33
标签
RSS
Links
小余和岁岁的个人博客
嘿嘿的博客
1 前言-浅析websocket 1.1 什么是websocket 1.2 为什么会有websocket 1.3 名称的由来 1.4 接口定义 1.5 协议基础 1.6 和http的关系(握手) 1.7 和socket的关系 2 环境准备 2.1 安装swoole 2.2 准备好jQuery.js 3 websocket_server.php 4 chat.html 5 启动服务 6 访问页面 7 构建整个IM需要考虑的问题 7.1 安全问题 7.2 性能问题 7.3 稳定性
2017 -
2020
Heimo
由 Jekyll 强力驱动
主题 -
NexT.Mist