FatKee

前面的文章是借鉴的                                                                                                                                                                                             

<?php
/**
 * @Author: FatKee
 * @Date:   2019-01-09 12:42:28
 * @Last Modified by:   FatKee
 * @Last Modified time: 2019-01-10 16:37:13
 */


class WebSocket{
    //socket池
    private $sockets = [];
    //用户池
    private $users = [];
    //主sock
    private $master = NULL;
    //当前错误
    private $error = \'\';
    public function __construct($host ,$port){
        $this->master = socket_create(AF_INET,SOCK_STREAM,SOL_TCP  );
        if($this->master === false){
            $this->error = \'socket create error\';
            exit;
        }
        if(socket_bind($this->master,$host,$port) === false){
            $this->error = \'socket bind error\';
             exit;
        }

        if(socket_listen($this->master) === false){
            $this->error = \'socket listen  error\';
             exit;
        }
        $this->sockets[] = $this->master;
        $this->e(\'start:\'.$host.\'port:\' . $port);


    }
    public function run(){
        while(true){
            $sockets = $this->sockets;
            $write = NULL;
            $except = NULL;
            socket_select($sockets,$write,$except,NULL);

            foreach($sockets as $sock){
                if($sock == $this->master){
                    //等待新用户
                    $k = uniqid();
                    $this->e(\'user:\'. $k . \' 加入用户池\');
                    $new_sock = socket_accept($this->master);


                    $this->users[$k] = array(\'socket\' => $new_sock, \'is_hand\' => false );
                    $this->sockets[]  = $new_sock;

                }else{
                    //接收消息的或者关闭链接
                    $k = $this->search($sock);
                    if($this->users[$k][\'is_hand\'] === false){
                        //进行握手
                        $this->handshake($sock);
                        $this->users[$k][\'is_hand\'] = true;
                        $this->e(\'user:\'. $k . \' 握手成功\');
                          continue;
                    }
                    //读取
                    $byte=socket_recv($sock, $buff,20480, 0);
                    if($byte<7){
                        $this->e(\'user:\'. $k . \' 退出\');
                        $this->close($k);
                        continue;
                    }

                    //$this->e(\'user:\'. $k . \' 发送消息\');
                    //转发消息给别人
                    $this->e($k.\'群发:\'.$this->decode($buff));
                    $this->qunfa($sock,$this->decode($buff));
                }

            }
        }
    }

    private function qunfa($sock,$str){
        foreach ($this->users as  $v) {
            if($v[\'socket\'] != $sock)
            $this->send($v[\'socket\'],$str);
        }
    }
    //寻找socket的key
    private function search($sock){
        foreach($this->users as $k=>$v){
            if($v[\'socket\'] == $sock){
                return $k;
            }
        }
    }

    private function handshake($sock){
        $c = socket_read($sock,1024);
        preg_match(\'/Sec-WebSocket-Key:(.*)/um\',$c,$str);
        if(isset($str[1])){
        $new_key = base64_encode(sha1(trim($str[1])."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
        $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
        $new_message .= "Upgrade: websocket\r\n";
        $new_message .= "Sec-WebSocket-Version: 13\r\n";
        $new_message .= "Connection: Upgrade\r\n";
        $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
        socket_write($sock,$new_message,strlen($new_message));
        }
    }
    //关闭链接
    private function close($k){
        socket_close($this->users[$k][\'socket\']);
        unset($this->users[$k]);
        $this->sockets = [];
        $this->sockets[] = $this->master;
        foreach($this->users as $v){
            $this->sockets[] = $v[\'socket\'];
        }
    }

    public function e($str){

        echo iconv(\'UTF-8\',\'GB2312\',$str) . "\r\n";
    }

    //解析数据
    private function decode($buff){
        $arr[\'fin\'] = ord($buff[0]) >> 7;
        $arr[\'mask\'] = ord($buff[1])>>7;
        $arr[\'len\'] = bindec(substr(decbin(ord($buff[1])),1,7));
        if($arr[\'len\'] == 126){
            $arr[\'len\'] = ord($buff[2]) + ord($buff[3]) ;
            $maskkey = substr($buff,4,4);
            $data = substr($buff,8);
        }
        if($arr[\'len\'] == 127){
            $arr[\'len\'] = ord($buff[2]) + ord($buff[3]) + ord($buff[4])+ ord($buff[5]);
            $maskkey = substr($buff,10,4);
            $data = substr($buff,14);
        }
        if($arr[\'len\']<=125){
            $maskkey = substr($buff,2,4);
            $data = substr($buff,6);
        }
        $a = "";
        for($i = 0 ; $i<strlen($data);$i++){
            $a .= $data[$i] ^ $maskkey[$i%4];
        }
        return $a;
    }
    private function send($sock,$str){
        $bf ="\x81".chr(strlen($str)).$str;
        socket_write($sock,$bf,strlen($bf));
    }
}

$socket = new WebSocket(\'192.168.2.188\',1234);

$socket->run();

                                                                                                                                                                                                                

分类:

技术点:

相关文章: