1. 程式人生 > >php從零搭建即時通訊(一.點對點聊天)

php從零搭建即時通訊(一.點對點聊天)

目錄

零.在thinkphp5環境下搭建gatewayWork環境

2.下載完成後解壓到你TP5專案的vendor目錄下即可,如圖

3.點選start_for_win.bat檔案即可成功啟動你的webSocked伺服器,如果你是linux的系統執行一下start.php檔案即可

dos介面如下即成功執行

一.在檢視檔案建立與webSocked伺服器的連線

因為是我的webSocked伺服器放在本地,所以地址就是127.0.0.1,到時候如果有需要,將地址改為你webSocked伺服器的地址就行

//連線websocket伺服器
let ws = new WebSocket("ws://127.0.0.1:8282");

坑:

有的瀏覽器可能預設沒有開啟webSocked,如果按照上面的程式碼你不能連線成功的話,可以根據的瀏覽器去設定一下即可

二.websocked伺服器向客戶端傳送訊息

注意伺服器所有的程式碼都在event檔案內編寫,並且改變該檔案內容和需要重啟webSocked伺服器

該檔案實體地址

D:\phpStudy2018\PHPTutorial\WWW\Qbling_mall\vendor\GatewayWorker\Applications\YourApp

在websocked伺服器上有三種傳送的方式

1.伺服器向所有客戶端傳送

Gateway::sendToAll($client_obj);

使用這行程式碼,伺服器就會向所有的與伺服器長連線的客戶端傳送訊息,其中$client_obj型別為字串由我們自定義,

我為了前後端互動方便,就將需要傳送的訊息的內容轉化為json物件

2.伺服器向某一客戶端傳送

 //當客戶端連線的時候,要求客戶傳送uid進行繫結
 Gateway::sendToClient($client_id,json_encode([
   'type'=>'init',
   'client_id' => $client_id
 ]));

使用這個方法,以後伺服器會向某個client_id傳送訊息,第一個引數為我們指定的client_id,第二個就是我們想要傳送的字串資訊

在這裡我們談談,client_id與uid,這兩個就像資料庫裡的主鍵一樣,

一個uid對應多個clientid,一個client_id只能對應一個uid

舉個例子,clientid就像你上學時的學號一樣,uid就像你的身份證號

你小學,中學,和大學的學號肯定不一樣吧,但是他們都對應你這個人

當我們使用長連線時,頁面的每一次重新整理,都會與伺服器都會重新給我們這個連結的客戶端生成一個新的clientid

就相當於你通過了高考,從高中到了大學,那麼你會重新獲得一個大學的學號,你的高中學號也就失去了意義,

但是,如果伺服器就想專門給你傳送一個訊息,怎麼辦呢,如果伺服器是給你的client_id傳送訊息,是很危險的

因為你這個客戶端可能中間重新整理了幾次,你的clientid就會像你的學號一樣發生了變化,所以可能會收不到資訊

這時候uid就出場了,它相當於你的身份證號,

伺服器直接給你的身份證號傳送訊息,它不管你現在處於什麼階段,clientid會不會改變,但是它知道你的uid是肯定不會變得,

所以伺服器就確保了這個資訊客戶端一定能收到(客戶端線上時)

3.伺服器向某一uid傳送(可能對應某幾個客戶端)

上面寫了對某一client_id傳送,那麼就肯定有對某一uid傳送啦,這裡引數基本與上面一致,就是clientid換成了uid

Gateway::sendToUid($client_obj->from_uid,json_encode([
     "type"=>"server_msg",
     "data"=>'繫結成功!'
]));

三.伺服器接受客戶端傳送的訊息

先簡單介紹下,伺服器端的三個回撥函式

1.onConnect

/**
     * 當客戶端連線時觸發
     * 如果業務不需此回撥可以刪除onConnect
     * 
     * @param int $client_id 連線id
     */
    

    public static function onConnect($client_id)
    {
        //code....
    }

2.onMessage

 /**
    * 當客戶端發來訊息時觸發
    * @param int $client_id 連線id
    * @param mixed $message 具體訊息
    */
   public static function onMessage($client_id, $message){

        //code..
    }

3.onClose

 /**
    * 當用戶斷開連線時觸發
    * @param int $client_id 連線id
    */
   public static function onClose($client_id)
   {
       //code...
   }

就這麼簡單的三個函式,

一個客戶端連結上伺服器的時候會觸發,onConnect函式,然後一直連著,

什麼時候覺得無聊了,給伺服器發個訊息,這時候就會觸發onMesssage函式

,當客戶端覺得沒意識,決定下線時,會觸發onClose

其中我們基本上絕大多數的業務處理都放在onMessage函式內,在這個函式內我們接受客戶端給我們傳送的資訊

舉個栗子

/**
    * 當客戶端發來訊息時觸發
    * @param int $client_id 連線id
    * @param mixed $message 具體訊息
    */
   public static function onMessage($client_id, $message)
   {
        //獲取客戶端傳送的json
        $client_obj = json_decode($message);
         
		//判斷使用者傳送的資訊的型別
		switch ($client_obj->type){
			//將client與客戶端的uid繫結
            case "bind":
                Gateway::bindUid($client_id,$client_obj->from_uid);
                Gateway::sendToUid($client_obj->from_uid,json_encode([
                    "type"=>"server_msg",
                    "data"=>'繫結成功!'
                ]));
                break;
            //code.............
            
            //判斷某個使用者是否線上
            case "is_online":
                $status = Gateway::isUidOnline($client_obj->to_uid);
                $data = [
                    "type" => "is_online",
                    "status" => $status,
                ];
                //向傳送者返回接受者是否線上的訊息
                Gateway::sendToUid($client_obj->from_uid,json_encode($data));
                break;
		}
		
   }

根據我們與事先定義好的內容,來進行對應的邏輯操作

四.客戶端向websocked伺服器傳送訊息

在客戶端給伺服器傳送訊息就簡單了

ws.send(JSON.stringify(send_obj));

先根據我們定義的與伺服器連結的物件中的send方法就完事了,

但是注意傳送的訊息也只能是字串哦,

所以我為了方便資料的互動,將伺服器與客戶端所有互動的資料全部轉成了json格式

五.客戶端接受websocked伺服器傳送的訊息

這個也很簡單

ws.onmessage = function(e){

    //code...
}

伺服器給客戶端傳送訊息時,會觸發們定義的與伺服器連結的物件中的onmessage方法

在這個方法裡面我們去寫相應的邏輯就歐克了