<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ? swoole的資料: https://wiki.swoole.com 主要看了 環境依賴、編譯安裝、快速起步 2. 起步 聊天室 websocket 參見ws.zip。 開始遇到的問題: 如何重載 Swoole提供了柔性終止/重啟的機制,管理員只需要向SwooleServer發送特定的信號,Server的worker進程可以安全的結束。 ? SIGTERM: 向主進程/管理進程發送此信號服務器將安全終止 ? 在PHP代碼中可以調用$serv->shutdown()完成此操作 ? SIGUSR1: 向主進程/管理進程發送SIGUSR1信號,將平穩地restart所有worker進程 ? 在PHP代碼中可以調用$serv->reload()完成此操作 ? swoole的reload有保護機制,當一次reload正在進行時,收到新的重啟信號會丟棄 ? 如果設置了user/group,Worker進程可能沒有權限向master進程發送信息,這種情況下必須使用root賬戶,在shell中執行kill指令進行重啟 由于swoole 是常駐內存的,如果修改了代碼 直接繼續發送包代碼是不生效的。需要reload 1. 設置進程標題,通過ps grep 查找來kill ~~~ cli_set_process_title('chat_process'); 這個mac? 不支持 kill -15 pid ~~~ 2. 將進程pid 寫入腳本,root用戶手動重啟 ~~~ ps -efH|grep swoole mac上 是 ps -efh|grep php $server->on('start',function($serv ) { ? ? // cli_set_process_title('chat_process'); ? ? $managerPid = $serv->manager_pid; ? ? $shString = <<<SH echo "Reloading..." kill -USR1 {$managerPid} echo "Reloaded" SH; $sh_file = '.reload_manager.sh'; ? ? file_put_contents($sh_file, $shString); }); ~~~ 3. 安裝inotify 擴展 監聽文件,將文件 在onWorkStart 回調中require_once. 監聽到文件變化了,自動重啟 參考sd框架 4. 鏈接的fd 不好感知是哪個設備,如何將針對不同設備形成定向廣播 $server->connection_list()? 獲取全部在線鏈接 5. 數據庫超時 暫時設置了數據庫的重連參數 'break_reconnect' => true, 6. 引入tp框架后,調試輸出的不顯示了 介入其他項目里的 alert dlert 函數 7. 報錯在終端不方便追蹤bug, 接管異常 設計同步方案 針對重載,在根目錄建立server_function.php workStart里 require_once ~~~ <?php function onMessage($server, $frame){ \Think\App::invokeClass('\app\index\controller\Message', [])->receive($server, $frame); } function onTask($server, $task_id, $src_worker_id, $data){ \Think\App::invokeClass('\app\index\controller\Task', [])->run($server, $task_id, $src_worker_id, $data); } function onClose($server, $fd){ ? ? $data = json_encode([ ? ? ? ? 'op'? ? ? => 'after_close', ? ? ? ? 'data'? ? => '', ? ? ? ? 'from_fd' => $fd, ? ? ], JSON_UNESCAPED_UNICODE); ? ? $server->task($data); } function onRequest ($server, $request, $response) { ? ? //請求過濾 ? ? if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') { ? ? ? ? return $response->end(); ? ? } // 環境常量 ? ? $response->header('Access-Control-Allow-Origin', "*"); $_SERVER = [ ? ? ? ? 'argv' => [], ? ? ]; ? ? $_GET? ? = $request->get?:[]; ? ? $_POST? ?= $request->post; ? ? foreach ($request->server as $key=>$value) { ? ? $_SERVER[strtoupper($key)] = $value; ? ? } ? ? $_COOKIE = $request->cookie; ? ? $_FILES? = $request->files; ? ? $ret = \Think\App::invokeClass('\app\index\controller\Index', [$server, $request, $response])->request(); ? ? $response->end($ret); ? ? exit(); } ~~~ 主文件index.php ~~~ <?php namespace think; global $server; $server = new \swoole_websocket_server("0.0.0.0", 9501); $server->set( ['task_worker_num'=>10] ); $server->on('start',function($serv ) { ? ? // cli_set_process_title('chat_process'); ? ? $managerPid = $serv->manager_pid; ? ? $shString = <<<SH echo "Reloading..." kill -USR1 {$managerPid} echo "Reloaded" SH; $sh_file = '.reload_manager.sh'; ? ? file_put_contents($sh_file, $shString); }); $server->on('WorkerStart',function($serv , $worker_id) { define('ERROR_LOG_TYPE', 'ws_error_log'); define('APP_PATH', __DIR__ . '/application/'); define('THINK_PATH', __DIR__ . '/thinkphp/'); // 加載框架引導文件 require_once __DIR__ . '/base.php'; $_SERVER = [ 'REQUEST_METHOD' => 'GET', 'argv'? ? ? ? ? ?=> [], ]; }); $server->on('open', function (\swoole_websocket_server $server, $request) { ? ? echo "server: handshake success with fd{$request->fd}\n"; }); $server->on('message', function (\swoole_websocket_server $server, $frame) { echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n"; $_SERVER['REQUEST_TIME'] = time(); App::initCommon(); require_once __DIR__. '/server_function.php'; ? ? onMessage($server, $frame); }); $server->on('close', function ($ser, $fd) { ? ? echo "client {$fd} closed\n"; require_once __DIR__. '/server_function.php'; ? ? onClose($ser, $fd); }); $server->on('finish', function ($ser, $fd) { ? ? return true; }); $server->on('task', function(\swoole_websocket_server $server, $task_id, $src_worker_id, $data){ App::initCommon(); require_once __DIR__. '/server_function.php'; onTask($server, $task_id, $src_worker_id, $data); return true; }); $server->start(); ~~~ 首先,參考?https://www.tuicool.com/articles/emY3Ar? 有了思路 ,然后閱讀tp5源碼 app 發現可以用靜態方法將 映射調用某個類,因此。 將task message 映射到Task 的run? 和 Message控制器 的 receive 方法里。 然后 定義數據格式為json 然后 反json后 動態op 參數調用內部方法。 消息的處理 經過討論,為了方便客戶端離線后臺看到消息,我們設計了數據表 ws_message表。 業務消息必然和shop_id table_id 相關,然后保存 發送方from_client_id 和接受方to_client_id 并記錄 發送消息設備類型 主還是副 經過討論,主設備發送消息 無需記錄, 消息 中data 和user_info 為序列化字段。 Message 類的組成 ~~~ <?php namespace app\index\controller; use app\common\lib\SystemLog; use app\index\model\WsDevices; use app\index\model\WsMessage; use app\index\model\WsOnlineClients; class Message { ? ? public function __construct() ? ? { ? ? ? ? config('default_return_type', 'json'); ? ? } ? ? public $from_fd; ? ? public $server; ? ? public $date_format = 'Y-m-d H:i:s'; ? ? public function success($info, $data = []) ? ? { ? ? ? ? debug('api_end'); ? ? ? ? $push_data = [ ? ? ? ? ? ? 'code'? ? ? => 0, ? ? ? ? ? ? 'msg'? ? ? ?=> $info, ? ? ? ? ? ? 'time'? ? ? => date($this->date_format, $_SERVER['REQUEST_TIME']), ? ? ? ? ? ? 'data'? ? ? => $data, ? ? ? ? ? ? 'ttfb_time' => debug('api_begin', 'api_end', 6) . 's', ? ? ? ? ]; ? ? ? ? return $this->server->push($this->from_fd, json_encode($push_data, JSON_UNESCAPED_UNICODE)); ? ? } ? ? public function error($info, $data = []) ? ? { ? ? ? ? debug('api_end'); ? ? ? ? $push_data = [ ? ? ? ? ? ? 'code'? ? ? => 1, ? ? ? ? ? ? 'msg'? ? ? ?=> $info, ? ? ? ? ? ? 'time'? ? ? => date($this->date_format, $_SERVER['REQUEST_TIME']), ? ? ? ? ? ? 'data'? ? ? => $data, ? ? ? ? ? ? 'ttfb_time' => debug('api_begin', 'api_end', 6) . 's', ? ? ? ? ]; ? ? ? ? return $this->server->push($this->from_fd, json_encode($push_data, JSON_UNESCAPED_UNICODE)); ? ? } ? ? public function receive($server, $frame) ? ? { ? ? ? ? debug('api_begin'); ? ? ? ? $data = $frame->data; ? ? ? ? $this->from_fd = $frame->fd; ? ? ? ? $this->server = $server; ? ? ? ? echo $data . '\n'; ? ? ? ? $data = json_decode($data, 1); ? ? ? ? if (is_array($data)) { ? ? ? ? ? ? if (method_exists($this, $data['op'])) { ? ? ? ? ? ? ? ? $call = $data['op']; ? ? ? ? ? ? ? ? unset($data['op']); ? ? ? ? ? ? ? ? $this->$call($server, $frame, $data); ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? goto rawMsg; ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? rawMsg: ? ? ? ? ? ? $this->rawMsg($server, $frame, $frame->data); ? ? ? ? } ? ? } ? ? // 登錄 ? ? public function login($server, $frame, $data) ? ? { ? ? ? ? // dlert2("fd:#{$frame->fd}|shop_id:{$data['shop_id']}|client_id:{$data['client_id']}|type:{$data['type']}的設備登錄了,".datetime()); ? ? ? ? WsDevices::login($frame->fd, $data['shop_id'], $data['client_id'], $data['type']); ? ? ? ? if($data['type'] == '主'){ ? ? ? ? ? ? // 登錄后重發數據, 客戶端重新鏈接后會重新拉去列表 ? ? ? ? ? ? // $data = json_encode([ ? ? ? ? ? ? //? ? ?'op'? ? ? ? => 'after_login', ? ? ? ? ? ? //? ? ?'client_id' => $data['client_id'], ? ? ? ? ? ? //? ? ?'from_fd'? ?=> $frame->fd, ? ? ? ? ? ? // ], JSON_UNESCAPED_UNICODE); ? ? ? ? ? ? // $server->task($data); ? ? ? ? } ? ? } ? ? // 登出 ? ? public function logout($server, $frame, $data) ? ? { ? ? ? ? $server->close($frame->fd); ? ? } ? ? // 加菜 退菜 打折 贈送 結賬 ? ? public function notify($server, $frame, $data) ? ? { ? ? ? ? if ($data['from_client_type'] == '主') { ? ? ? ? ? ? $sub_clients = WsDevices::getSubClientByShopId($data['shop_id']); ? ? ? ? ? ? if ($sub_clients) { ? ? ? ? ? ? ? ? $sub_client_ids = array_column($sub_clients, 'client_id'); ? ? ? ? ? ? ? ? $fds = WsOnlineClients::where('client_id', 'in', $sub_client_ids)->column('fd'); ? ? ? ? ? ? ? ? foreach ($fds as $fd) { ? ? ? ? ? ? ? ? ? ? $server->push($fd, $data); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? $main_clients = WsDevices::getMainClientByShopId($data['shop_id']); ? ? ? ? ? ? if ($main_clients) { ? ? ? ? ? ? $ws_message_client_ids = []; ? ? ? ? ? ? ? ? foreach ($main_clients as $main_client) { ? ? ? ? ? ? ? ? ? ? $id = WsMessage::add($data['shop_id'], $data['table_id'], $data['type'], $data['data'], $data['user_info'], $data['from_client_id'], $main_client['client_id'], '副', $data['status']); ? ? ? ? ? ? ? ? $ws_message_client_ids[$main_client['client_id']] = $id; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? $main_client_ids = array_column($main_clients, 'client_id'); ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? if ($main_client_ids) { ? ? ? ? ? ? ? ? ? ? $fds = WsOnlineClients::where('client_id', 'in', $main_client_ids)->column('client_id,fd'); ? ? ? ? ? ? ? ? ? ? $online_messages = array_intersect_key($ws_message_client_ids, $fds); ? ? ? ? ? ? ? ? ? ? foreach ($fds as $client_id=>$fd) { ? ? ? ? ? ? ? ? ? ? if(isset($online_messages[$client_id])){ ? ? ? ? ? ? ? ? ? ? $msg_id = $online_messages[$client_id]; ? ? ? ? ? ? ? ? ? ? $push_data = [ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'id'? ? ? ?=> $msg_id,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'status'? ?=> $data['status'],? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'table_id' => $data['table_id'],? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'type'? ? ?=> $data['type'], ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'title'? ? => "桌id:{$data['table_id']} {$data['type']}", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? $info = $server->connection_info($fd); ? ? ? ? ? ? ? ? ? ? ? ? ? ? if($info['websocket_status'] == 3){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $ret = $server->push($fd, json_encode($push_data, JSON_UNESCAPED_UNICODE)); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if($ret){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? WsMessage::where('id', $msg_id)->update(['is_delivered'=>1]); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $fail_msg = sprintf('時間:%s,店鋪id:%d下子設備 client_id:%s 向主設備client_id %s發送 【桌號id:%s,類型:%s,消息id:%d】的消息失敗', datetime(),$data['shop_id'], $data['from_client_id'], $client_id, $data['table_id'], $data['type'], $msg_id); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? alert(__CLASS__.':'.__FUNCTION__.':L'.__LINE__.PHP_EOL.$fail_msg); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dlert(__CLASS__.':'.__FUNCTION__.':L'.__LINE__.PHP_EOL.$fail_msg); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SystemLog::error_log($fail_msg, __CLASS__.':'.__FUNCTION__.':L'.__LINE__, ERROR_LOG_TYPE); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? $this->error('店鋪主設備未記錄,請先聯系商家完成主設備初始化'); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? // 處理非序列化消息 ? ? public function rawMsg($server, $frame, $msg) ? ? { ? ? ? ? $server->push($frame->fd, "{$frame->data}"); ? ? ? ? // dlert2($msg); ? ? ? ? if (stripos($msg, '說') !== false) { ? ? ? ? ? ? $data = json_encode([ ? ? ? ? ? ? ? ? 'op' => 'say', ? ? ? ? ? ? ? ? 'data' => $msg, ? ? ? ? ? ? ? ? 'from_fd' => $frame->fd, ? ? ? ? ? ? ], JSON_UNESCAPED_UNICODE); ? ? ? ? ? ? $server->task($data); ? ? ? ? } ? ? ? ? // 獲取特殊管理的消息 ? ? ? ? if (stripos($msg, 'from_admin') !== false) { ? ? ? ? ? ? parse_str($msg, $params); ? ? ? ? ? ? dump($params); ? ? ? ? ? ? $op = $params['op']; ? ? ? ? ? ? switch ($op) { ? ? ? ? ? ? ? ? case 'reload': ? ? ? ? ? ? ? ? ? ? echo 'reloading server'; ? ? ? ? ? ? ? ? ? ? $server->reload(); ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? case 'get_connections': ? ? ? ? ? ? ? ? ? ? $server->push($frame->fd, json_encode($server->connection_list() ?: [], JSON_UNESCAPED_UNICODE)); ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? case 'send_messages': ? ? ? ? ? ? ? ? ? ? $data = json_encode([ ? ? ? ? ? ? ? ? ? ? ? ? 'op'? ? ? => 'admin_say', ? ? ? ? ? ? ? ? ? ? ? ? 'data'? ? => $params['content'], ? ? ? ? ? ? ? ? ? ? ? ? 'from_fd' => $frame->fd, ? ? ? ? ? ? ? ? ? ? ? ? 'to_fds'? => $params['to_fds'], ? ? ? ? ? ? ? ? ? ? ], JSON_UNESCAPED_UNICODE); ? ? ? ? ? ? ? ? ? ? $server->task($data); ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? default: ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? } ? ? } } ~~~ rawMsg? 是用于不是json 格式的字符串,處理消息。用于客戶端測試 echo服務器。和其他特殊命令 login? 用于自定義登錄消息,記錄在線設備,更新設備狀態 logout 下線(設備-刪除ws_online_clients)記錄。通過手動close fd 抓onClose里的 task 異步任務。 notify 主要邏輯 主要用于 產生消息記錄,并廣播至同店鋪主設備(多個主設備比較復雜,需要二次同步,不實現)。push成功后更新is_delived 字段 http接口 1.獲取消息列表(待處理-shop_id)ws.weiwoju.com/api.php/index/index/messageList/shop_id/{shop_id} 直接查詢 2. 處理標記消息 ws.weiwoju.com/api.php/index/index/deal/{id:1,status} 3. 獲取主設備在線狀態 ws.weiwoju.com/api.php/index/index/check_online_main/shop_id/{shop_id} 其實就是查詢online表和devices 表的 4. http 內請求websocket ws.weiwoju.com/api.php/index/index/notify_main/ 參數見代碼 和web端請求格式一致。 進程模型 ssl開啟 生成證書: SSL支持 本章將詳細講解如何制作證書以及如何開啟Swoole的SSL的單向、雙向認證。 準備工作 選擇任意路徑,執行如下命令創建文件夾結構 ~~~ mkdir ca cd ca mkdir private mkdir server mkdir newcerts ~~~ 在ca目錄下創建openssl.conf文件,文件內容如下 ~~~ [ ca ] default_ca = foo # The default ca section [ foo ] dir = /path/to/ca # top dir database = /path/to/ca/index.txt # index file. new_certs_dir = /path/to/ca/newcerts # new certs dir certificate = /path/to/ca/private/ca.crt # The CA cert serial = /path/to/ca/serial # serial no file private_key = /path/to/ca/private/ca.key # CA private key RANDFILE = /path/to/ca/private/.rand # random number file default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = md5 # message digest method to use unique_subject = no # Set to 'no' to allow creation of # several ctificates with same subject. policy = policy_any # default policy [ policy_any ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = match localityName = optional commonName = optional emailAddress = optional ~~~ 其中,/path/to/ca/是ca目錄的絕對路徑。 創建ca證書 在ca目錄下創建一個shell腳本,命名為new_ca.sh。文件內容如下: ~~~ #!/bin/sh openssl genrsa -out private/ca.key openssl req -new -key private/ca.key -out private/ca.csr openssl x509 -req -days 365 -in private/ca.csr -signkey private/ca.key -out private/ca.crt echo FACE > serial touch index.txt openssl ca -gencrl -out private/ca.crl -crldays 7 -config "./openssl.conf" ~~~ 執行sh new_ca.sh命令,創建ca證書。生成的證書存放于private目錄中。 注意?在創建ca證書的過程中,需要輸入一些信息。其中,countryName、stateOrProvinceName、organizationName、organizationalUnitName這四個選項的內容必須要填寫,并且需要記住。在生成后續的證書過程中,要保證這四個選項的內容一致。 創建服務端證書 在ca目錄下創建一個shell腳本,命名為new_server.sh。文件內容如下: ~~~ #!/bin/sh openssl genrsa -out server/server.key openssl req -new -key server/server.key -out server/server.csr openssl ca -in server/server.csr -cert private/ca.crt -keyfile private/ca.key -out server/server.crt -config "./openssl.conf" ~~~ 執行sh new_ca.sh命令,創建ca證書。生成的證書存放于server目錄中。 創建客戶端證書 在ca目錄下創建一個shell腳本,命名為new_client.sh。文件內容如下: ~~~ #!/bin/sh base="./" mkdir -p $base/users/ openssl genrsa -des3 -out $base/users/client.key 1024 openssl req -new -key $base/users/client.key -out $base/users/client.csr openssl ca -in $base/users/client.csr -cert $base/private/ca.crt -keyfile $base/private/ca.key -out $base/users/client.crt -config "./openssl.conf" openssl pkcs12 -export -clcerts -in $base/users/client.crt -inkey $base/users/client.key -out $base/users/client.p12 ~~~ 執行sh new_ca.sh命令,創建ca證書。生成的證書存放于users目錄中。 進入users目錄,可以看到有一個client.p12文件,這個就是客戶端可用的證書了,但是這個證書是不能在php中使用的,因此需要做一次轉換。命令如下: ~~~ openssl pkcs12 -clcerts -nokeys -out cer.pem -in client.p12 openssl pkcs12 -nocerts -out key.pem -in client.p12 ~~~ 以上兩個命令會生成cer.pem和key.pem兩個文件。其中,生成key.pem時會要求設置密碼,這里記為client_pwd 注意?如果在創建客戶端證書時,就已經給client.p12設置了密碼,那么在轉換格式的時候,需要輸入密碼進行轉換 最終結果 以上步驟執行結束后,會得到不少文件,其中需要用的文件如下表所示: | 文件名 | 路徑 | 說明 | | --- | --- | --- | | ca.crt | ca/private/ | ca證書 | | server.crt | ca/server/ | 服務器端證書 | | server.key | ca/server/ | 服務器端秘鑰 | | cer.pem | ca/client/ | 客戶端證書 | | key.pem | ca/client/ | 客戶端秘鑰 | SSL單向認證 Swoole開啟SSL Swoole開啟SSL功能需要如下參數: ~~~ $server = new swoole_server("127.0.0.1", "9501" , SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL ); $server = new swoole_http_server("127.0.0.1", "9501" , SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL ); ~~~ 并在swoole的配置選項中增加如下兩個選項: ~~~ $server->set(array( 'ssl_cert_file' => '/path/to/server.crt', 'ssl_key_file' => '/path/to/server.key', )); ~~~ 這時,swoole服務器就已經開啟了單向SSL認證,可以通過https://127.0.0.1:9501/進行訪問。 SSL雙向認證 服務器端設置 雙向認證指服務器也要對發起請求的客戶端進行認證,只有通過認證的客戶端才能進行訪問。 為了開啟SSL雙向認證,swoole需要額外的配置參數如下: ~~~ $server->set(array( 'ssl_cert_file' => '/path/to/server.crt', 'ssl_key_file' => '/path/to/server.key', 'ssl_client_cert_file' => '/path/to/ca.crt', 'ssl_verify_depth' => 10, )); ~~~ 客戶端設置 這里我們使用CURL進行https請求的發起。 首先,需要配置php.ini,增加如下配置: `curl.cainfo=/path/to/ca.crt` 發起curl請求時,增加如下配置項: ~~~ $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 只信任CA頒布的證書 curl_setopt($ch, CURLOPT_SSLCERT, "/path/to/cer.pem"); curl_setopt($ch, CURLOPT_SSLKEY, "/path/to/key.pem"); curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERTPASSWD, '******'); // 創建客戶端證書時標記的client_pwd密碼 ~~~ 這時,就可以發起一次https請求,并且被swoole服務器驗證通過了。 服務端域名 要開啟那個ssl: ~~~ listen? ? ? ?443 ssl; ? ? ssl_certificate? ? ? server.crt; ? ? ssl_certificate_key? server.key; ? ? ssl_session_cache? ? shared:SSL:1m; ? ? ssl_session_timeout? 5m; ? ? ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ? ? ssl_ciphers? HIGH:!aNULL:!MD5; ? ? ssl_prefer_server_ciphers? on; ~~~ 這樣 443 后ssl? 去掉ssl on? 可以 混合訪問 生成配置中的一些設置,經過測試不填host可以任意域名: ~~~ Country Name (2 letter code) []:CN State or Province Name (full name) []:Zhejiang Locality Name (eg, city) []:Hangzhou Organization Name (eg, company) []:weiwoju Organizational Unit Name (eg, section) []:ws password = weiwoju ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看