websocket实现了服务器与客户端的双向通信,即使客户端没有请求,服务器端也可以主动发送消息。
部分主要代码如下:
public function run(){
$this->service(); //开启websocket函数
$clients[] = $this->_sockets; //服务器端连接信息 clients数组保存着已连接用户的标识信息
while (true){ //挂起进程
$changes = $clients;
$write = NULL;
$except = NULL;
//如果是新连接 是只有服务器端是活跃的 $this->_sockets永远是服务器端
//如果是发送消息,是某个客户端活跃 如果是某个客户断开连接,这个客户也视为活跃
socket_select($changes, $write, $except, NULL); //筛选活跃连接,如果没有活跃连接将阻塞程序。
foreach ($changes as $key => $_sock){
if($this->_sockets == $_sock){ //判断是不是新接入的socket
if(($newClient = socket_accept($_sock)) === false){
die('failed to accept socket: '.socket_strerror($_sock)."\n");
}
$line = trim(socket_read($newClient, 1024));
$this->handshaking($newClient, $line); //握手处理函数
socket_getpeername ($newClient, $ip); //获取client ip
$clients[] = $newClient;
echo "Client ip:{$ip} \n";
echo "Client msg:{$line} \n";
} else {
socket_recv($_sock, $buffer, 2048, 0);
$msg = $this->message($buffer); //解析接受数据函数
//在这里业务代码
echo "{$key} clinet msg:",$msg,"\n";
fwrite(STDOUT, 'Please input a argument:');
$response = trim(fgets(STDIN));
$this->send($_sock, $response); //发送消息函数
echo "{$key} response to Client:".$response,"\n";
}
}
}
}
while(true)通过无限循环来挂起程序。
socket_select()函数的作用就是筛选活跃的连接(就是有新消息到或者有客户端连接/断开)如果有,程序继续执行,如果没有,阻塞程序执行。
socket_select ($changes, $write = NULL, $except = NULL, NULL);
$changes是所有已连接用户,当它有变化(就是有新消息到或者有客户端连接/断开)时,socket_select()函数会把活跃连接筛选出来并返回给$changs,程序继续往下执行。
$write是监听是否有客户端写数据,传入NULL是不关心是否有写变化。
$except是$sockets里面要被排除的元素,传入NULL是监听全部。
最后一个参数是超时时间,这里设为null:如遇某一个连接有新动态,则返回。