费话不多讲,具体看代码
1.服务端实现
class Ws{ private $host = '127.0.0.1'; private $port = 8080; private $maxuser = 10; private $socket; public $accept = []; private $isHand = []; private $cycle = []; public function __construct($host,$port,$maxuser) { $this->host = $host; $this->port = $port; $this->maxuser = $maxuser; } public function start() { // 创建一个Socket $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); //允许使用本地地址 socket_set_option($this->socket,SOL_SOCKET,SO_REUSEADDR,TRUE); // 绑定地址和端口 socket_bind($this->socket,$this->host,$this->port); //侦听 socket_listen($this->socket,$this->maxuser); while(True){ $this->cycle = $this->accept; $this->cycle[] = $this->socket; //阻塞用,有新连接时才会结束 socket_select($this->cycle, $write, $except, null); //轮询 foreach($this->cycle as $key =>$v){ if($v === $this->socket){ //当接受一个Socket不成功时,继续下一个 if(($accept = socket_accept($v))<0){ continue; } //添加到循环池 $this->add_accept($accept); continue; } // 获得当前连接健值 $index = array_search($v,$this->accept); if($index === null){ continue; } // 接受客户端数据 if( !@socket_recv($v,$data,1024,0) || !$data){ $this->close($v); continue; } // 握手并发送用户连接数 if(!$this->isHand[$index]){ $this->upgrade($v,$data,$index); call_user_func_array('user_add_callback',array($this)); continue; } $data = $this->decode($data); // 发送数据 call_user_func_array('send_callback', array($data, $index, $this)); } sleep(1); } }
回调
function send_callback($data, $index, $ws) { $data = json_encode(array( 'text' => $data, 'user' => $index, )); send_to_all($data, 'text', $ws);}function send_to_all($data, $type, $ws){ $res = array( 'msg' => $data, 'type' => $type, ); $res = json_encode($res); $res = $ws->frame($res); print_r($ws->accept); foreach ($ws->accept as $key => $value) { socket_write($value, $res, strlen($res)); }}function close_callback($ws) { $data = count($ws->accept); send_to_all($data, 'num', $ws);}function user_add_callback($ws) { $data = count($ws->accept); send_to_all($data, 'num', $ws);}
客户端实现
websocket聊天室 在线人数