這里我們用的是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協議。