启用 Socket 服务器
ModPHP 提供了一个默认的 Socket 服务器程序逻辑,用以配合模块数据操作。
要启动默认的 Socket 服务器,你只需要在服务器的控制台中运行站点根目录的 socket-server.php 文件即可。如果你使用 Apache 服务器,你也可以在浏览器中开启,但需要验证管理员权限。注意:浏览器可能无法加载 socket-server.php 页面输出的内容,访问后直接关闭窗口即可。
监听端口由 config('mod.SocketServer.port') 设置,默认为 8080。
开启 Socket 服务器不会影响正常的 Apache 网站,但是如果你的程序代码经过改动(例如更新系统),则需要重新启动 Socket 服务。如果你是在浏览器中启用 Socket 服务器的,那么你需要通过关闭 Apache 来关闭 Socket 服务器,然后才能再次重启它。
当 Socket 服务器启动之后,你就可以通过 JSON 进行数据交换了,所有能够通过 URL 访问 mod.php 进行请求的操作,也能通过 Socket 服务器进行。
该 Socket 服务器仅用于传输文本数据(JSON),不支持传输二进制数据,但是,你可以将二进制数据转换为文本(例如图像转 base64)进行传输,或者自己编写另外的 Socket 程序逻辑。
客户端通过发送 JSON 数据向服务器提交请求,服务器将操作结果回应以 JSON 数据,实现前后端一致。需要注意的是,除非是重现会话,否则 JSON 中必须包含 {obj} 和 {act} 属性,其他属性将作为请求参数。
重现会话:
如果客户端已经通过其他方式进行了用户登录,如 AJAX,那么可以将 cookie 中的 Session ID 传给 Socket 服务器,从而在 WebSocket 中恢复登录状态。当然,如果你没有通过其他方式进行登录,也可以使用 WebSocket 进行登录,登录后会将用户信息和 Session ID 通过 JSON 同时返回给客户端,客户端将 Session ID 写入 Cookie 中,从而在浏览其他页面时也保持会话。
重现会话示例:
var ws = new WebSocket('ws://localhost:8080');
ws.open = function(){
var sid = document.cookie.match(/PHPSESSID=(.*)\b/)[1];
ws.send(JSON.stringify({PHPSESSID: sid}));
}
登录示例:
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function(){
var data = {
obj: 'user',
act: 'login',
user: 'someone',
user_password: 'not_show_here'
};
ws.send(JSON.stringify(data));
}
ws.onmessage = function(e){
var result = JSON.parse(e.data);
if(result.success && result.PHPSESSID){
document.cookie += 'PHPSESSID='+result.PHPSESSID; //将 Session ID 写到 cookie 中
}
}
需要注意的是,在重现会话或者使用 WebSocket 进行登录之后,之后的其他操作就已经运行在已登录状态了,服务器会保存登录信息,不需要客户端再提交 Session ID。例如,要获取当前登录用户的信息,只需要这样做:
ws.send(JSON.stringify({obj: 'user', act: 'getMe'}));
Socket 服务器也支持页面判断功能,需要客户端发送数据时同时发送 HTTP_REFERER 为当前 URL 地址给服务器(自定义来路页面)。例如上面获取当前用户信息的例子,可以这样:
ws.send(JSON.stringify({obj: 'user', act: 'getMe', HTTP_REFERER: location.href}));
虽然,ModPHP 提供了非常便捷的搭建 Socket 服务器的方法,但是你必不可滥用它。例如,在一个 HTML 页面,你应该只设置一个指向同一服务器的 WebSocket 的实例。更好的就是,使用 iframe 等方式,实现多个页面使用同一个 WebSocket 实例。这样可以有效地节约服务器资源,从而加快网站运行速度。
其他客户端类型连接服务器:
其他客户端类型或者其他编程语言编写得 Socket 客户端的连接和通讯与 WebSocket 大同小异,但和 WebSocket 协议相比,这些客户端不需要使用复杂的编码和解码过程,直接发送原始报文即可。
ModPHP 提供了在 Socket 服务器下进行网站地址判断的功能(如果網站地址未固定),这个特性,是依赖客户端发送的握手包来实现的。在 WebSocket 协议中,客户端会将一个 HTTP 请求头作为握手包发送给服务器。ModPHP 利用这个请求头,来计算出网站的 URL 地址。
因此,你也可以在普通的 Socket 连接中,发送一个 HTTP 请求头格式的数据,作为握手包,来让服务器自动“计算”网站的 URL 地址。
将 WebSocket 运行于多线程中:
请查看《将 Socket 服務器运行于多线程环境中》。