PHP websocket学习笔记
- <?php
- <?php
-
- class Ws {
-
- // 服务器端的socket
- private $mainSocket;
- // socket队列
- public $socketList = [];
- // 连接事件
- public $onConnection;
- // 会话事件
- public $onMessage;
- // 关闭事件
- public $onClose;
-
-
- // 构造函数
- public function __construct() {
- // 创建socket
- $this->mainSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
- // IP和端口重用
- socket_set_option($this->mainSocket, SOL_SOCKET, SO_REUSEADDR, 1);
- // 绑定
- socket_bind($this->mainSocket, '0.0.0.0', 6060);
- // 监听
- socket_listen($this->mainSocket, 5);
- // 把服务器端的socket存入socket队列
- $this->socketList[(int)$this->mainSocket] = $this->mainSocket;
- }
-
- // 运行
- public function run() {
-
- // 让服务不停止
- while (true) {
- $read = $this->socketList;
- $write = $except = null;
- // 删除不活跃的socket
- $status = socket_select($read, $write, $except, null);
- if (!$status) continue;
-
- foreach ($read as $socket) {
- // 第一次来访问
- if ($this->mainSocket == $socket) {
- // 得到客户端的socket
- $clientSocket = socket_accept($socket);
- // 获取客户端头信息进行握手操作
- $headData = socket_read($clientSocket, 8000);
- handshaking($headData, $clientSocket);
-
- socket_getpeername($clientSocket, $addr, $port);
-
- // 把客户端的一个socket存入队列中
- $this->socketList[(int)$clientSocket] = $clientSocket;
- $read[(int)$clientSocket] = $clientSocket;
- // 删除掉
- unset($read[(int)$this->mainSocket]);
-
- // 注册一个事件
- if ($this->onConnection) {
- call_user_func($this->onConnection, $clientSocket);
- }
- } else {
- // 获得客户发送过来的数据
- $buf = socket_read($socket, 8000);
- // 关闭或异常
- if ($buf === '' || $buf === false) {
- // 删除掉队列它socket
- unset($read[(int)$socket]);
- unset($this->socketList[(int)$socket]);
- if ($this->onClose){
- call_user_func($this->onClose);
- }
- socket_close($socket);
- continue;
- }else{
- if ($this->onMessage){
- call_user_func($this->onMessage,$socket,$buf);
- }
- }
- }
- }//End foreach
- }// End while
- }//End run
-
-
- }
-
-
- $server = new Ws();
-
- // 连接
- $server->onConnection = function ($socket){
- $msg = (int)$socket."欢迎进入web60聊天室 !";
- socket_write($socket,enmask($msg));
- };
- // 会话
- $server->onMessage = function ($socket,$data){
- $msg = unmask($data);
- // 广播给所有人 聊天室
- broadcast($msg);
- };
-
- $server->run();
-
-
- /**
- * @param $msg 广播的消息
- */
- function broadcast($msg){
-
- global $server;
- foreach ($server->socketList as $socket){
- $tmp = enmask((int)$socket.'说:'.$msg);
- @socket_write($socket,$tmp);
- }
- }
-
-
- /**
- * @param $header 客户端头信息
- * @param $activeSocket 客户端的socket对象
- */
- function handshaking($header, $activeSocket) {
- preg_match("/Sec-WebSocket-Key: (.+)rn/", $header, $matchs);
- $key = base64_encode(sha1($matchs[1] . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
- $head = "HTTP/1.1 101 Switching Protocolsrn";
- $head .= "Upgrade: websocketrn"; // 告诉这个websocket客户端可以把这个协议升级为websocket协议
- $head .= "Connection: Upgradern"; // 升级这个通信协议
- $head .= "Sec-WebSocket-Accept: {$key}rnrn"; // 最后的一定要有两个回车
- // 握手响应协议信息返回给浏览器
- socket_write($activeSocket, $head);
- }
-
- //解码数据
- function unmask($text) {
- $length = ord($text[1]) & 127;
- if ($length == 126) {
- $masks = substr($text, 4, 4);
- $data = substr($text, 8);
- } elseif ($length == 127) {
- $masks = substr($text, 10, 4);
- $data = substr($text, 14);
- } else {
- $masks = substr($text, 2, 4);
- $data = substr($text, 6);
- }
- $text = "";
- for ($i = 0; $i < strlen($data); ++$i) {
- $text .= $data[$i] ^ $masks[$i % 4];
- }
- return $text;
- }
-
- // 加码数据
- function enmask($str) {
- $a = str_split($str, 125);
- $ns = "";
- foreach ($a as $o) {
- $ns .= "\x81" . chr(strlen($o)) . $o;
- }
- return $ns;
- }
- ?>
解压密码: detechn或detechn.com
免责声明
本站所有资源出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户自行鉴别,做一个有主见和判断力的用户。
本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。