这里我们用的是WorkerMan框架,服务器是CentOS,Web服务器是Apache,开发语言是PHP。
因为WSS是WebSocket和SSL的结合,所以需要提前准备好对应域名的SSL证书,一般情况下是三个证书文件,比如下面:
SSLCertificateFile "/www/wwwroot/test.crt"
SSLCertificateKeyFile "/www/wwwroot/test.key"
SSLCertificateChainFile "/www/wwwroot/test-ca-bundle.crt"
好,开始吧!
搭建可以端口访问的WSS协议长连接环境
我以端口号39001(必须接入防火墙白名单)为例,代码如下:
<?php require_once __DIR__ . \'/Workerman/Autoloader.php\'; use Workerman\Worker; // 证书最好是申请的证书 $context = array( \'ssl\' => array( // 请使用绝对路径 \'local_cert\' => \'/www/wwwroot/test.pem\', // 也可以是crt文件 \'local_pk\' => \'/www/wwwroot/test.key\', \'verify_peer\' => false, // \'allow_self_signed\' => true, //如果是自签名证书需要开启此选项 ) ); // 这里设置的是websocket协议(端口任意,但是需要保证没被其它程序占用) $worker = new Worker(\'websocket://0.0.0.0:39001\', $context); // 设置transport开启ssl,websocket+ssl即wss $worker->transport = \'ssl\'; $worker->onMessage = function($con, $msg) { $con->send(\'ok\'); }; Worker::runAll();
这样搭建完之后,Workerman就监听了端口为39001的wss协议,客户端就可以通过wss协议来连接workerman实现安全即时通讯了。
客户端的测试连接代码如下,可以通过打开chrome浏览器,按F12打开调试控制台,在Console一栏输入,或者把下面代码放入到html页面用js运行。
1 ws = new WebSocket("wss://www.bojuwang.net:39001"); 2 ws.onopen = function() { 3 alert("WSS连接成功"); 4 ws.send(\'伯驹网络\'); 5 alert("给服务端发送一个字符串:伯驹网络"); 6 }; 7 ws.onmessage = function(e) { 8 alert("收到服务端的消息:" + e.data); 9 };
握手连接过程中如果出现404或者503的错误,一般是程序的问题,请自己检查。返回200说明整体连接成功。
这样我们就搭建了一个完整的WSS环境,可以使用了。但是小程序的WSS还比较特殊,因为它不允许使用443(SSL服务的默认端口)之外的端口,也就是我们只能使用这样的wss://www.bojuwang.net连接网址而不能使用这样带端口的wss://www.bojuwang.net:39001。这就需要我们使用Apache的代理服务,来解决这个问题。
搭建小程序WSS协议长连接环境(不带端口)
首先,我们先创建监听39001的WebSocket,然后通过Apache代理将ws协议转为wss协议。
使用Workerman创建监听
<?php require_once __DIR__ . \'/workerman/Autoloader.php\'; use Workerman\Worker; use Workerman\Lib\Timer; $ws_worker = new Worker("websocket://0.0.0.0:39001"); $ws_worker->count = 4; // 当收到客户端发来的数据$data,处理之后发送给客户端 $ws_worker->onMessage = function($connection, $data) { // 向客户端发送消息 $connection->send(\'5,\'.$data.\',1\'); }; // 运行worker Worker::runAll();
这个时候我们使用上面的测试方法连接ws协议的网址是可以成功的,接下来将ws转换成wss。首先启用Apache的SSL连接配置以及代理模块,这一步非常重要,如果不启用的话,代理就无法生效。
具体启用方法找到apache的httpd.conf,启用代理模块,方法如下:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
然后启用SSL安全连接:
# Secure (SSL/TLS) connections
Include conf/extra/httpd-ssl.conf
具体的连接配置在这个httpd-ssl.conf文件中。然后我们找到httpd-ssl.conf文件进行如下配置:
Listen 443 <VirtualHost *:443> # Proxy Config SSLProxyEngine on ProxyRequests Off DocumentRoot "/www/wwwroot/" ServerName www.bojuwang.net:443 SSLEngine on SSLProtocol all -SSLv2 -SSLv3 SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM SSLHonorCipherOrder on SSLCertificateFile "/www/wwwroot/test.crt" SSLCertificateKeyFile "/www/wwwroot/test.key" SSLCertificateChainFile "/www/wwwroot/test-ca-bundle.crt" <Directory "/www/wwwroot/"> AllowOverride All Require all granted </Directory> ProxyPass / ws://0.0.0.0:39001 ProxyPassReverse / ws://0.0.0.0:39001 </VirtualHost>
配置过程中监听端口不要重复,否则重启apache时会报错。
各个代理路径证书路径也要注意,否则也会报错。
至此,大功告成!
这个时候服务器监听到443的SSL请求,就会代理到39001长连接端口,实现了WSS协议。