头像加载失败

阅读量:
评论数:

图片加载失败

前言

WebSocket是一种在单个TCP连接上进行全双工通讯的协议。和使用ajax之类http请求所不同的是,Websocket允许服务端主动向客户端推送数据,同时也避免了使用ajax轮询造成的服务器资源浪费或者长连接带来的性能问题。也就是这个特性,使得它在很多场景得到应用,最典型的就是聊天功能。

使用原生PHP写socket比较繁琐,所以这里用workerman框架进行 PHP socket 的开发。

使用ws

workerman开发手册
workerman的Github传送门

基本的使用自行查看workerman手册,这里主要讲一下我个人开发过程的思路。

1.刚连接时 - 验证身份

由于是常驻内存的运行机制,无法像之前一样实时读写session;
并且是由于非HTTP协议的应用,与HTTP协议相关的变量函数(包括session)都无法直接使用。

虽然workerman框架提供了封装在Workerman\Protocols\Http类里面替代的HTTP函数,但是在非http协议的应用中是用不了session和cookie的。

在这里我是使用的redis去实现对当前用户是否真正登录的验证,从而决定是否允许其继续保持websocket连接。(不过这一步我做的不是很严谨,有兴趣可以看代码找漏洞)

2.发送消息时 - 对同一个用户所保持的所有websocket连接群发消息

一个用户可能在浏览器上同时开了多个页面,而websocket是无法对多个浏览器页面保持同一个连接的(这是不现实的),所以需要存储一个用户所同时保持的websocket连接(用connect_id标识)

当一个用户通过websocket发送消息时,附带上接收者ID,然后服务器通过redis找到接收者所保持的所有websocket连接(用redis set存储),进而将消息发送给这几个连接:

同样的,一个用户在一个页面发送了消息,他打开的其他页面也要同步显示刚发送的消息,用同样的方法实现。

3.断开连接时 - 清除redis上的存储信息

使用wss

其实我一开始是用的MeepoPS框架(也是一个PHP socket的框架),后来部署到服务器上发现实现了全站https的缘故,无法正常使用ws协议;而MeepoPS又不支持wss协议(websocket的基于SSL的安全传输协议),因而马上转手workerman。

使用workerman实现wss协议非常简单,详见 创建wss服务 - workerman手册

在这之前,首先要有SSL证书(pem/crt文件及key文件),可参考上一篇博客 Linux Server + Nginx 配置HTTPS

不啰嗦,贴代码

以及,前端代码要改为:

  1. ws = new WebSocket("wss://myafei.cn:19910"); //使用域名+端口号

最后

在这个网站注册登录后,可通过导航栏右边 Hello, {YourUserName} 处点击进入个人中心,你会看到和我的聊天窗口的(笑

PC端

PC端聊天窗口

手机端

手机端页面

手机端聊天窗口

附录(代码)

整个网站的源代码,放在Github上了:传送门