<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [toc] ## :-: **跑官方demo** 常見的協議分3種: ### :-: **1、使用HTTP協議對外提供Web服務** ![](https://box.kancloud.cn/f39fa24250edf2a6ef051cced2c330ce_1196x645.png) >[warning]注意: 1、瀏覽器訪問不了,可能是因為端口沒開(或關防火墻) ![](https://box.kancloud.cn/b3b07c8e65e95b0443df2ede77a322b7_994x223.png) 2、如果你使用curl命令來訪問的話,要在新開的(當前shell標簽右鍵單擊復制ssh渠道)bash中輸入指令 3、開發必讀里(守護進程才用的到重啟。) ![](https://box.kancloud.cn/d7d1de3ac926fcc09e2f6c2faf2a1483_494x57.png) \> php 文件名?restart?#重啟php ### :-: **2、使用WebSocket協議對外提供服務** >[danger]看圖中圈的,客戶端的代碼要改ip ![](https://box.kancloud.cn/6293f5cae0ce28a3b5df6e4436ebbeb4_490x219.png) ### :-: **3、直接使用TCP傳輸數據** ![](https://box.kancloud.cn/2b06ac720527c35ff06e1ae94385f07a_495x427.png) ![](https://box.kancloud.cn/7bcfc5a0cbb5ef3db82f3646c8f83e36_602x110.png) Ctrl + \] ?#關閉telnet 在輸入quit >[warning]如果報錯說,沒有telnet,可參考https://www.cnblogs.com/ikai/p/7073201.html #安裝telnet ## :-: **示例代碼,簡單聊天室** >[info]此處使用的是,WebSocket協議對外提供服務 - 建議學習之前,先學下websocket。可參考本書路徑:/前端常用知識點/其他/websocket - 首先拋開別的不談,咱先捋明白業務邏輯,不然看了代碼也是懵逼 - 既然做聊天室(說白了就是類似QQ,一對一聊天) - 1、聊天首先要有昵稱(花名) - 2、必須登錄后才能聊天 - 3、聊天還要找到對方(我們開發肯定是找ip,而不是和聊QQ去根據名字找好友)后在發送消息 ### :-: **思路** >[info]總思路:客戶端發給服務端,服務端處理完,js還要解析顯示在html上 1. 認證服務器(登錄) - 客戶端發送登錄消息 - 服務端處理 - 使用正則判斷,截取用戶名 - 將登錄用戶的ip和昵稱,保存起來,以后做判斷用 - 解析完返回消息(客戶端標識登錄) 2. 發消息 - 客戶端發送普通消息 - 并將客戶端發送的消息,顯示出來 - 服務端處理 - 使用正則判斷,截取用戶名 - 判斷發消息的客戶端,是否通過服務器認證(是否登錄了) - 通過認證的,才可以往客戶端發送消息 - 客戶端解析服務端返回消息 - 將解析好的信息,顯示出來 3. 廣播,顯示昵稱 - 服務端 - 拼接要返回的數據,轉成json - 遍歷,拿當前和服務器連接的客戶端,發消息給客戶端 - 客戶端 - 解析服務端返回的數據,遍歷將他顯示在昵稱列表上 4. 單播,一對一聊天 - 客戶端 - 通過選擇用戶昵稱 - 將消息發給某個用戶 - 服務端,通過服務端轉發 - 解析發過來的數據,取接收方的ip和要發的消息 - 判斷接收方是否登錄了,登錄才可發送 - 使用接收方的$connection對象發送數據 - 客戶端 - 解析服務端發過來的數據 - 將其在接收方顯示出來 5. 關閉客戶端 - 在數組中刪除已經登錄的用戶 6. 關閉服務端 - 將登錄標識置為false >[info]以下是寫這個例子我參考的優質博客,大家可以參考 - http://blog.csdn.net/github_26672553/article/details/54932788 - http://blog.csdn.net/github_26672553/article/details/54946302 - http://blog.csdn.net/github_26672553/article/details/55098197 ### :-: **客戶端代碼** ~~~ html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="txtcontent" style="width: 500px;height: 250px;border: 1px solid gray"></div> <div>所有用戶:<select id="listuers"></select></div> <div>你的昵稱:<input type="text" id="username" /></div> <div> 回復內容: <textarea style="width: 500px;height: 100px" id="txtmsg"></textarea> </div> <div> <button onclick="connectServer()">連接服務器</button> <button onclick="send()">發送消息</button> </div> <script> var socket = null; //將socket實例保存到變量中 var isLogin = false; //登錄標識符 //1、鏈接服務端 function connectServer(){ var username = document.getElementById('username').value; //如果用戶名為空 if(username == ''){ alert('用戶昵稱不能為空'); } //2、實例化 socket = new WebSocket('ws://47.94.21.171:2000'); //3、打開的時候,發送消息 socket.onopen = function(){ socket.send('login:' + username); //誰登錄了 }; //4、接收服務器返回的數據 socket.onmessage = function(e){ //console.log(e); var getMsg = e.data; //返回的數據 //解析getMsg。思路:通過正則匹配,顯示出來 if(/^notice:success$/.test(getMsg)){ //服務端驗證通過 isLogin = true; }else if(/^msg:/.test(getMsg)){ //將服務端返回的普通消息顯示出來 var p = document.createElement('P'); //將msg:替換為空 p.innerHTML = '<span>服務端返回的消息:</span>' + getMsg.replace('msg:',''); document.getElementById('txtcontent').appendChild(p); //追加節點 }else if(/^users:/.test(getMsg)){ //廣播(將所有用戶昵稱顯示出來) //console.log(getMsg); nicheng = getMsg.replace('users:',''); //{"61.144.116.123":"yangxi"} shownicheng = eval('('+nicheng+')'); //轉json var listusers = document.getElementById('listuers'); listusers.innerHTML = ''; //先清空 for(var key in shownicheng){ var option = document.createElement('option'); option.value = key; //ip option.innerHTML = shownicheng[key]; //將昵稱填充進去 listusers.appendChild(option); //追加節點 } }else if(/^dian:/.test(getMsg)){ //單播(點對點發消息) //console.log(getMsg); var p = document.createElement('P'); //創建節點 //將msg:替換為空 p.innerHTML = '<span>單播的消息:</span>' + getMsg.replace('dian:',''); document.getElementById('txtcontent').appendChild(p); //追加節點 } }; //5、服務端關閉 socket.onclose = function(){ isLogin = false; alert('服務器斷開'); }; } //發送消息按鈕 function send(){ if(!isLogin){ alert('請先通過服務器驗證'); } //獲取要發送的內容 var msg = document.getElementById('txtmsg').value; //發送消息給服務端 socket.send('msg:' + msg); //單聊,點對點發送消息 var listusers = document.getElementById('listuers'); var toUserIPP = listusers.options[listusers.selectedIndex].value; //收消息的ip var toUserName = listusers.options[listusers.selectedIndex].text; //收消息的昵稱 socket.send('dian:<' + toUserIPP + '>:' + msg); //將發出的普通消息顯示出來 var p = document.createElement('p'); p.innerHTML = '<span>客戶端發出的消息:</span>' + msg; document.getElementById('txtcontent').appendChild(p); } </script> </body> </html> ~~~ ### :-: **服務端代碼** ~~~ php <?php /** * 注釋最全,跑碼版 * User: Administrator * Date: 2018/3/12 * Time: 10:48 */ use Workerman\Connection\AsyncTcpConnection; use Workerman\Worker; require '../Workerman/Autoloader.php'; $clients = []; //保存客戶端信息 //1、創建一個worker監聽,使用websocket協議 $ws_worker = new Worker('websocket://0.0.0.0:2000'); //開啟4個進程 $ws_worker->count = 4; //2、接收客戶端發來的數據 $ws_worker->onMessage = function($connection,$data){ global $clients; //2.1、用戶點擊的是(鏈接服務器)驗證客戶端 if(preg_match('/^login:(\w{3,20})/i',$data,$result)){ $ip = $connection->getRemoteIp(); //獲取當前客戶端IP $port = $connection->getRemotePort(); //獲取當前客戶端端口 if(!array_key_exists($ip,$clients)){ //判斷該ip是否登錄過 //$clients[$ip] = $result[1]; //新登錄的ip保存起來 $clients[$ip.':'.$port] = ['ipp'=>$ip.':'.$port,'name'=>$result[1],'conn'=>$connection]; //廣播的話,不止保存昵稱,還要保存ip和當前和服務器連接的那個客戶端 //將處理完的信息返回給客戶端(給客戶端發送任意消息) $connection->send('notice:success'); $connection->send('msg:你好'.$result[1]); echo $ip . ':'.$port . '--------' .$result[1] . 'login' . PHP_EOL; //打印看結果 //一旦有用戶登錄,就把保存的客戶端信息發過去(顯示出所有用戶) //$connection->send('users:'.json_encode($clients)); //廣播(群聊) $users = 'users:'.json_encode(array_column($clients,'name','ipp')); //返回數組中指定的列 foreach($clients as $ip=>$client){ //拿當前和服務器連接的那個客戶端,發送消息 $client['conn']->send($users); } } }else if(preg_match('/^msg:(.*?)/isU',$data,$megset)){ //2.2、處理發來的普通消息 if(array_key_exists($connection->getRemoteIp(),$clients)){ //判斷該ip是否存在,存在就是已經登錄的 echo '用戶:' . $connection->getRemoteIp() . '發的消息是' . $megset[1] . PHP_EOL; if($megset[1] == 'nihao'){ $connection->send('msg:nihao'.$clients[$connection->getRemoteIp()]); } //我認為廣播應該在這些,將用戶A說的話,顯示到頁面上,讓所有用戶都能看見 } }else if(preg_match('/^dian:\<(.*?)\>:(.*?)/isU',$data,$meg)){ //單播,點對點發消息 $ipp = $meg[1]; //接收消息用戶的ip $msg = $meg[2]; //發送的數據 $name = $clients[$ipp]['name']; echo "<pre>"; var_dump($name); if(array_key_exists($ipp,$clients)){ //接收的ip也登錄了,也就是有這個用戶 $clients[$ipp]['conn']->send('dian:'.$msg); echo $ipp.'==>'.$msg.PHP_EOL; } } }; //客戶端關閉 $ws_worker->onClose = function($connection){ global $clients; //echo $clients[$connection->getRemoteIp()].'客戶端已斷開'.PHP_EOL; unset($clients[$connection->getRemoteIp()]); }; //3、運行 Worker::runAll(); ~~~ ## :-: **其他示例** >[info]示例:黑/白名單訪問 ~~~ php <?php require_once __DIR__.'/Workerman/Autoloader.php'; use Workerman\Worker; $worker = new Worker('tcp://0.0.0.0:8085'); // 連接回調 $worker->onConnect = function ($connection){ // IP 白名單驗證 if($connection->getRemoteIP() != '127.0.0.1'){ $connection->close("IP Address Forbidden"); } }; // 接受發送消息 $worker->onMessage = function ($conn,$data){ $conn->send("Hello World"); }; // 關閉連接 $worker->onClose = function ($connection){ echo "connection close \n"; }; $worker::runAll(); ~~~ - 開啟Workerman服務 ![](https://box.kancloud.cn/d8997ec60e45b9ea5e072b97d90484ca_423x130.png) - 正確的訪問 ![](https://box.kancloud.cn/0c94aceb35808b545f11cfbb87cec378_488x87.png) - 非本地地址訪問 ![](https://box.kancloud.cn/a4555920cd90b7ecdd4bb1e4e5e9ef23_393x70.png) ## :-: **雜記** ![](https://box.kancloud.cn/3dd490bdaff03238a1a121ac11b7ce09_1437x348.png) - Worker是容器,監聽特定端口 - 當客戶端連接到這個端口,會在容器內部產生一個connection對象 - Worker容器,可能有很多個connection對象 - 通過操作connection對象向客戶端發送和接收數據等操作 - 有2個connection類: - TcpConnection類(連接類的基類);客戶端連接上之后自動產生的connection對象; - AsyncTcpConnection(是TcpConnection的子類);當我們<span style="color:red;">在workerman之后需要訪問一個web服務</span>,可以通過這個類異步的發起一個http鏈接,去鏈接遠程的服務端,異步的通訊;該類是客戶端連接其他服務端所用到的類
                  <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>

                              哎呀哎呀视频在线观看