1 <?php 2 //2、設計一個循環掛起WebSocket通道,進行數據的接收、處理和發送 3 //對創建的socket循環進行監聽,處理數據 4 function run(){ 5 //死循環,直到socket斷開 6 while(true){ 7 $changes=$this->sockets; 8 $write=NULL; 9 $except=NULL; 10 /* 11 //這個函數是同時接受多個連接的關鍵,我的理解它是為了阻塞程序繼續往下執行。 12 socket_select ($sockets, $write = NULL, $except = NULL, NULL); 13 $sockets可以理解為一個數組,這個數組中存放的是文件描述符。當它有變化(就是有新消息到或者有客戶端連接/斷開)時,socket_select函數才會返回,繼續往下執行。 14 $write是監聽是否有客戶端寫數據,傳入NULL是不關心是否有寫變化。 15 $except是$sockets里面要被排除的元素,傳入NULL是”監聽”全部。 16 最后一個參數是超時時間 17 如果為0:則立即結束 18 如果為n>1: 則最多在n秒后結束,如遇某一個連接有新動態,則提前返回 19 如果為null:如遇某一個連接有新動態,則返回 20 */ 21 socket_select($changes,$write,$except,NULL); 22 foreach($changes as $sock){ 23 //如果有新的client連接進來,則 24 if($sock==$this->master){ 25 //接受一個socket連接 26 $client=socket_accept($this->master); 27 //給新連接進來的socket一個唯一的ID 28 $key=uniqid(); 29 $this->sockets[]=$client; //將新連接進來的socket存進連接池 30 $this->users[$key]=array( 31 'socket'=>$client, //記錄新連接進來client的socket信息 32 'shou'=>false //標志該socket資源沒有完成握手 33 ); 34 //否則1.為client斷開socket連接,2.client發送信息 35 }else{ 36 $len=0; 37 $buffer=''; 38 //讀取該socket的信息,注意:第二個參數是引用傳參即接收數據,第三個參數是接收數據的長度 39 do{ 40 $l=socket_recv($sock,$buf,1000,0); 41 $len+=$l; 42 $buffer.=$buf; 43 }while($l==1000); 44 //根據socket在user池里面查找相應的$k,即健ID 45 $k=$this->search($sock); 46 //如果接收的信息長度小於7,則該client的socket為斷開連接 47 if($len<7){ 48 //給該client的socket進行斷開操作,並在$this->sockets和$this->users里面進行刪除 49 $this->send2($k); 50 continue; 51 } 52 //判斷該socket是否已經握手 53 if(!$this->users[$k]['shou']){ 54 //如果沒有握手,則進行握手處理 55 $this->woshou($k,$buffer); 56 }else{ 57 //走到這里就是該client發送信息了,對接受到的信息進行uncode處理 58 $buffer = $this->uncode($buffer,$k); 59 if($buffer==false){ 60 continue; 61 } 62 //如果不為空,則進行消息推送操作 63 $this->send($k,$buffer); 64 } 65 } 66 } 67 } 68 } 69 ?>
