用的是nginx代理轉發443到2120端口實現,官方說workman原生支持,沒有實現(現象是 訪問 htttps://域名:2120/ 超時,不知道是服務器問題仍是什麼)php
後轉爲用nginx代理轉發實現css
一、假設用https://socket.test.com 做爲socket鏈接的地址. https://www.test.com仍是網站自己,實現共存,不影響主站訪問html
一、nginx的 網站.conf,注意紅色部分。2121那個轉發不是必須的,由於是服務端curl請求,能夠直接請求ip地址帶端口ios
server { listen 443; server_name *.test.com test.com; set $flag 0; if ($host != 'www.test.com') { set $flag "${flag}1"; } if ($host = 'socket.test.com'){ set $flag "${flag}1"; } if ($flag = "01"){ rewrite ^/(.*)$ http://www.test.com/$1 permanent; } #if ($host != 'www.test.com' ) { # } ssl on; ssl_certificate cert/cert-1542176077391__.test.com.crt; ssl_certificate_key cert/cert-1542176077391__.test.com.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; index index.html index.htm index.php default.html default.htm default.php; root /home/wwwroot/test; error_page 404 /404.html; location /push.api { proxy_pass http://127.0.0.1:2121; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-Real-IP $remote_addr; } location /socket.io { proxy_pass http://127.0.0.1:2120; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-Real-IP $remote_addr; } location /{ if (!-e $request_filename) { rewrite ^/(.+\.(html|xml|json|htm|php|jsp|asp|shtml))$ /index.php?$1 last; } # Deny access to PHP files in specific directory #location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; } include enable-php5.2.conf; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /.well-known { allow all; } location ~ /\. { deny all; } #access_log /home/wwwlogs/test.com.log; }
二、服務端socket.io.php,無需更改。仍是用端口2120,不用開啓sslnginx
<?php use Workerman\Worker; use Workerman\WebServer; use Workerman\Lib\Timer; use PHPSocketIO\SocketIO; include __DIR__ . '/vendor/autoload.php'; // 全局數組保存uid在線數據 $uidConnectionMap = array(); // 記錄最後一次廣播的在線用戶數 $last_online_count = 0; // 記錄最後一次廣播的在線頁面數 $last_online_page_count = 0; // PHPSocketIO服務 $sender_io = new SocketIO(2120); // 客戶端發起鏈接事件時,設置鏈接socket的各類事件回調 $sender_io->on('connection', function($socket){ file_put_contents('/home/wwwroot/test/home/socketioserver.txt',date('Y-m-d H:i:s')."\r\n connection:uid:".$uid."\r\n=======\r\n",FILE_APPEND); /**/ // error_reporting(E_ALL ^ E_NOTICE); //$root_dir = realpath(dirname(__FILE__).'/../'); //require_once($root_dir."/config/config.php"); /* require_once(APP_DIR.'/base/kernel.php'); @require_once(APP_DIR.'/base/defined.php'); if(!kernel::register_autoload()){ require_once(APP_DIR.'/base/autoload.php'); }*/ /**/ // 當客戶端發來登陸事件時觸發 $socket->on('login', function ($uid)use($socket){ file_put_contents('/home/wwwroot/test/home/socketioserver.txt',date('Y-m-d H:i:s')."\r\n login:uid:".$uid."\r\n=======\r\n",FILE_APPEND); global $uidConnectionMap, $last_online_count, $last_online_page_count; // 已經登陸過了 if(isset($socket->uid)){ return; } // 更新對應uid的在線數據 $uid = (string)$uid; if(!isset($uidConnectionMap[$uid])) { $uidConnectionMap[$uid] = 0; } // 這個uid有++$uidConnectionMap[$uid]個socket鏈接 ++$uidConnectionMap[$uid]; /* $dbs= kernel::database(); $dbs->exec('update sdb_b2c_online_users set online="'.serialize($uidConnectionMap).'"');*/ //file_put_contents(HOME_DIR.'/chat/OnlineUsersCache.txt',serialize($uidConnectionMap)); //app::get('b2c')->setConf('chat.online_users',$uidConnectionMap); // 將這個鏈接加入到uid分組,方便針對uid推送數據 $socket->join($uid); $socket->uid = $uid; // 更新這個socket對應頁面的在線數據 $socket->emit('update_online_count',count($uidConnectionMap)); }); // 當客戶端斷開鏈接是觸發(通常是關閉網頁或者跳轉刷新致使) $socket->on('disconnect', function () use($socket) { file_put_contents('/home/wwwroot/test/home/socketioserver.txt',date('Y-m-d H:i:s')."\r\n disconnect:uid:".$socket->uid."\r\n=======\r\n",FILE_APPEND); if(!isset($socket->uid)) { return; } global $uidConnectionMap, $sender_io; // 將uid的在線socket數減一 if(--$uidConnectionMap[$socket->uid] <= 0) { unset($uidConnectionMap[$socket->uid]); } // file_put_contents(HOME_DIR.'/chat/OnlineUsersCache.txt',serialize($uidConnectionMap)); }); }); // 當$sender_io啓動後監聽一個http端口,經過這個端口能夠給任意uid或者全部uid推送數據 $sender_io->on('workerStart', function(){ // 監聽一個http端口 $inner_http_worker = new Worker('http://0.0.0.0:2121'); // 當http客戶端發來數據時觸發 $inner_http_worker->onMessage = function($http_connection, $data){ $_POST = $_POST ? $_POST : $_GET; if($_POST['appkey']!='fads'){ // return $http_connection->send('fail'); } // 推送數據的url格式 type=publish&to=uid&content=xxxx switch(@$_POST['type']){ //聊天 case 'publish': global $sender_io; $to = @$_POST['to']; $_POST['content'] = (@$_POST['content']); // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('new_msg', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('new_msg', @$_POST['content']); } // http接口返回ok return $http_connection->send('ok'); break; //新的拍賣出價時 case 'new_auction_price': global $sender_io; $to = @$_POST['to']; $_POST['content'] = (@$_POST['content']); // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('new_auction', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('new_auction_price', @$_POST['content']); } return $http_connection->send('ok'); break; //建立拍賣 case 'create_auction': global $sender_io; $to = @$_POST['to']; // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('create_auction', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('create_auction', @$_POST['content']); } return $http_connection->send('ok'); break; //延遲 case 'delay_auction': global $sender_io; $to = @$_POST['to']; // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('delay_auction', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('delay_auction', @$_POST['content']); } return $http_connection->send('ok'); break; //流拍 case 'cancel_auction': global $sender_io; $to = @$_POST['to']; // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('cancel_auction', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('cancel_auction', @$_POST['content']); } return $http_connection->send('ok'); break; //開始今日拍賣時+切換到下一個拍賣時+結束當日拍賣到下一個拍賣時 case 'change_domain_item': global $sender_io; $to = @$_POST['to']; // 有指定uid則向uid所在socket組發送數據 if($to){ $sender_io->to($to)->emit('change_domain_item', $_POST['content']); // 不然向全部uid推送數據 }else{ $sender_io->emit('change_domain_item', @$_POST['content']); } return $http_connection->send('ok'); } return $http_connection->send('fail'); }; // 執行監聽 $inner_http_worker->listen(); // 一個定時器,定時向全部uid推送當前uid在線數及在線頁面數 Timer::add(1, function(){ global $uidConnectionMap, $sender_io, $last_online_count, $last_online_page_count; $online_count_now = count($uidConnectionMap); $online_page_count_now = array_sum($uidConnectionMap); // 只有在客戶端在線數變化了才廣播,減小沒必要要的客戶端通信 if($last_online_count != $online_count_now || $last_online_page_count != $online_page_count_now) { $sender_io->emit('update_online_count', $online_count_now); $last_online_count = $online_count_now; $last_online_page_count = $online_page_count_now; } }); }); if(!defined('GLOBAL_START')) { Worker::runAll(); }
三、客戶端js.最大的坑就是這裏。原先覺得io('地址'),是要填完整的,好比下面web
<script src='https://socket.test.com/web-msg-sender-master/socket.io-client/socket.io.js?v=123123'></script>
<script>
$(document).ready(function () {
// 建立WebSocket 對象
var socket = io("https://socket.test.com/socket.io",{debug:true});
/*
* 2019-08-24 11:27:35
connection:uid:
=======
2019-08-24 11:28:04
disconnect:uid:
*
* */
//var socket = io("http://118.190.21.61:2120",{debug:true});
/*
* 2019-08-24 11:26:08
connection:uid:
=======
2019-08-24 11:26:08
login:uid:1566617168000
=======
2019-08-24 11:26:35
disconnect:uid:1566617168000
=======
* */
//鏈接成功時,觸發事件
// 鏈接後登陸
console.log('socket',socket);
socket.on('connect', function(){
socket.emit('login', uid);
});
// 後端推送來消息時
socket.on('new_msg', function(msg){
$('#content').html('收到消息:'+msg);
$('.notification.sticky').notify();
});
// 後端推送來在線數據時
socket.on('update_online_count', function(online_stat){
$('#online_box').html(online_stat);
});
})
</script>
後來發現怎麼也連不上socket服務,on事件監聽徹底失效。json
後來看了 lib/manager.js裏源碼才知道,系統會自動補全socket.io,因此初始化時io裏變量只需填寫域名便可,正確以下。注意紅色加粗部分後端
<script src='https://socket.test.com/web-msg-sender-master/socket.io-client/socket.io.js?v=123123'></script> <script> $(document).ready(function () { // 建立WebSocket 對象 var socket = io("https://socket.test.com",{debug:true}); /* * 2019-08-24 11:27:35 connection:uid: ======= 2019-08-24 11:28:04 disconnect:uid: * * */ //var socket = io("http://118.190.21.61:2120",{debug:true}); /* * 2019-08-24 11:26:08 connection:uid: ======= 2019-08-24 11:26:08 login:uid:1566617168000 ======= 2019-08-24 11:26:35 disconnect:uid:1566617168000 ======= * */ //鏈接成功時,觸發事件 // 鏈接後登陸 console.log('socket',socket); socket.on('connect', function(){ socket.emit('login', uid); }); // 後端推送來消息時 socket.on('new_msg', function(msg){ $('#content').html('收到消息:'+msg); $('.notification.sticky').notify(); }); // 後端推送來在線數據時 socket.on('update_online_count', function(online_stat){ $('#online_box').html(online_stat); }); }) </script>