iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0
自我挑戰組

挑戰30天完成PHP聊天室範例系列 第 23

[Day23]第二十二章-盤古開天(十)-WEBSOCKET SERVER端(4)

  • 分享至 

  • xImage
  •  

接續上一篇,
我們要先確認連過來的client是新的連線,
還是已經握手過的人要傳訊息然後判斷後續要做什麼,
如果是一個新的連線,我們必須先接受他,
所以要使用內建函數socket_accept(),
然後因為要做匿名聊天室,
我們給進來的連線一個不重複的id(使用uniqid函數),

//對創建的socket循環進行監聽,處理數據
function run(){
    //循環,直到socket斷開
    while(true){
         socket_select($changes,$write,$except,NULL);
         //循環取client傳過來的資料
         foreach($changes as $sock){
             //如果有新的client連接進來,則
            if($sock==$this->master){
              //接受一個socket連接
              $client=socket_accept($this->master);
              //给新連接進來的socket一個唯一的ID
              $key=uniqid();
              $this->sockets[]=$client; //將新連接進來的socket存進連接池
              $this->users[$key]=array(
              'socket'=>$client, //紀錄新連接進來client的socket訊息
              'shou'=>false    //標記該socket資源沒有完成握手
          );
            }else{
            //do some
            }
         }
    }
}

再來是要處理如果有人要傳訊息時的處理,
需要使用到socket_recv()內建函數接收資料,
還要根據socket在user池裡面查找相應的$k,ID
建立一個search()的自訂函數

//根據sock在users裡面查找相應的$k
  function search($sock){
    foreach ($this->users as $k=>$v){
      if($sock==$v['socket'])
      return $k;
    }
    return false;
  }

然後組裝我們剛說的

//對創建的socket循環進行監聽,處理數據
function run(){
    //循環,直到socket斷開
    while(true){
         socket_select($changes,$write,$except,NULL);
         //循環取client傳過來的資料
         foreach($changes as $sock){
             //如果有新的client連接進來,則
            if($sock==$this->master){
              //接受一個socket連接
              $client=socket_accept($this->master);
              //给新連接進來的socket一個唯一的ID
              $key=uniqid();
              $this->sockets[]=$client; //將新連接進來的socket存進連接池
              $this->users[$key]=array(
              'socket'=>$client, //紀錄新連接進來client的socket訊息
              'shou'=>false    //標記該socket資源沒有完成握手
          );
            }else{
              $len=0;
              $buffer='';
              //讀取該socket的訊息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度
              do{
                $l=socket_recv($sock,$buf,1000,0);
                $len+=$l;
                $buffer.=$buf;
              }while($l==1000);

              //根據socket在user池裡面查找相應的$k,即ID
              $k=$this->search($sock);
            }
         }
    }
}

下一篇繼續努力~~


上一篇
[Day22]第二一章-盤古開天(九)-WEBSOCKET SERVER端(3)
下一篇
[Day24]第二十三章-盤古開天(十一)-WEBSOCKET SERVER端(5)
系列文
挑戰30天完成PHP聊天室範例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
淺水員
iT邦大師 6 級 ‧ 2018-10-31 12:10:41

謝謝您的文章
正好在學這部分

剛剛我在想能不能夠把 resource 作為陣列的 key
這樣在查詢時會方便很多
於是搜尋到這篇文章
裡面說到可以用 spl_object_hash 函數把 resource 轉為一個 unique id
這樣查詢的效能是 O(1)

如果這樣用沒什麼問題的話
我會偏好這種方法

我要留言

立即登入留言