• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

WebSocket中的长连接以及超时问题的解决问题(代码)

php 搞代码 4年前 (2022-01-21) 14次浏览 已收录 0个评论

本篇文章给大家带来的内容是关于WebSocket中的长连接以及超时问题的解决问题(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

<?phpset_time_limit(0);class SocketService{    private $address  = 'localhost';    private $port = 80;    private $_sockets;    public function __construct($address = '', $port='')    {        if(!empty($address)){            $this->address = $address;        }        if(!empty($port)) {            $this->port = $port;        }    }    public function service(){        //获取tcp协议号码。        $tcp = getprotobyname("SOL_TCP");           # 获取与协议名称关联的协议号        $sock = socket_create(AF_INET, SOCK_STREAM, $tcp);  # 创建一个套接字(通讯节点)        socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);  # 设置套接字选项        if($sock < 0)        {            throw new Exception("failed to create socket: ".socket_strerror($sock)."\n");        }        socket_bind($sock, $this->address, $this->port);    # 绑定        socket_listen($sock, $this->port);      # 监听套接字上的连接        $this->_sockets = $sock;       }    public function run(){        $this->service();        $clients[] = $this->_sockets;   # 数组存储 每个socket        # 让服务器无限获取客户端传过来的信息        while (true){            $changes = $clients;            $write = NULL;            $except = NULL;            socket_select($changes,  $write,  $except, NULL);            foreach ($changes as $key => $_sock){                if($this->_sockets == $_sock){  # 判断是不是新接入的socket                    if(($newClient = socket_accept($_sock))  === false){    # 接受新的套接字上的连接   socket_accept的作用就是接受socket_bind()所绑定的主机发过来的套接流                        die('failed to accept socket: '.socket_strerror($_sock)."\n");  # 返回描述套接字错误的字符串                    }                    $line = trim(socket_read($newClient, 1024));  # 读取客户端传过来的资源,并转化为字符串     socket_read的作用就是读出socket_accept()的资源并把它转化为字符串                    $this->handshaking($newClient, $line);                    //获取client ip                    socket_getpeername ($newClient, $ip);                                   # 查询给定套接字的远程端,这可能导致主机/端口或UNIX文件系统路径,具体取决于其类型。                    $clients[$ip] = $newClient;                } else {                    # 读取该socket的信息,注意:第二个参数是引用传参即接收数据,第三个参数是接收数据的长度                    $lenght = socket_recv($_sock, $buffer,  2048, 0);               # 从已连接的socket接收数据   $lenght 接收到字符串长度    <b style="color:transparent">来&源gao@dai!ma.com搞$代^码%网</b><img>搞gaodaima代码</img>                $msg = $this->message($buffer);          # 接收到的信息                    //在这里业务代码                    fwrite(STDOUT, 'Please input a argument:');                    $response = trim(fgets(STDIN));//                    $this->send($_sock, $response);                                                       # 第二个参数是获取数据    要发送的信息                    $this->send($_sock, '在线');                }            }        }    }    /**     * 握手处理     * @param $newClient socket     * @return int  接收到的信息     */    public function handshaking($newClient, $line){        $headers = array();        $lines = preg_split("/\r\n/", $line);   # 通过一个正则表达式分隔字符串。        foreach($lines as $line)        {            $line = chop($line);    # 移除字符串右端的空白字符或其他预定义字符            if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))            {                $headers[$matches[1]] = $matches[2];            }        }        $secKey = $headers['Sec-WebSocket-Key'];        $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));        $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .            "Upgrade: websocket\r\n" .            "Connection: Upgrade\r\n" .            "WebSocket-Origin: $this->address\r\n" .            "WebSocket-Location: ws://$this->address:$this->port/服务器地址\r\n".            "Sec-WebSocket-Accept:$secAccept\r\n\r\n";        return socket_write($newClient, $upgrade, strlen($upgrade));    # socket_write的作用是向socket_create的套接流写入信息,或者向socket_accept的套接流写入信息    }    /**     * 解析接收数据     * @param $buffer     * @return null|string     */    public function message($buffer){        $len = $masks = $data = $decoded = null;        $len = ord($buffer[1]) & 127;        if ($len === 126)  {            $masks = substr($buffer, 4, 4);            $data = substr($buffer, 8);        } else if ($len === 127)  {            $masks = substr($buffer, 10, 4);            $data = substr($buffer, 14);        } else  {            $masks = substr($buffer, 2, 4);            $data = substr($buffer, 6);        }        for ($index = 0; $index < strlen($data); $index++) {            $decoded .= $data[$index] ^ $masks[$index % 4];        }        return $decoded;    }    /**     * 发送数据     * @param $newClinet 新接入的socket     * @param $msg   要发送的数据     * @return int|string     */    public function send($newClinet, $msg){        $msg = $this->frame($msg);        socket_write($newClinet, $msg, strlen($msg));   # 写入套接字    }    public function frame($s) {        $a = str_split($s, 125);    # 把字符串分割到数组中 第二个长度参数        if (count($a) == 1) {            return "\x81" . chr(strlen($a[0])) . $a[0];        }        $ns = "";        foreach ($a as $o) {            $ns .= "\x81" . chr(strlen($o)) . $o;        }        return $ns;    }    /**     * 关闭socket     */    public function close(){        # socket_close的作用是关闭socket_create()或者socket_accept()所建立的套接流        return socket_close($this->_sockets);    }}$sock = new SocketService();$sock->run();

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:WebSocket中的长连接以及超时问题的解决问题(代码)
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址