php实现websocket实时消息推送

来源:互联网 发布:淘宝广告商品被删 编辑:程序博客网 时间:2024/06/02 07:30

php实现websocket实时消息推送
这里写图片描述

SocketService.php

<?php/** * Created by xwx * Date: 2017/10/18 * Time: 14:33 */class SocketService{    private $address  = '0.0.0.0';    private $port = 8083;    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("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);        echo "listen on $this->address $this->port ... \n";        $this->_sockets = $sock;    }    public function run(){        $this->service();        $clients[] = $this->_sockets;        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){                        die('failed to accept socket: '.socket_strerror($_sock)."\n");                    }                    $line = trim(socket_read($newClient, 1024));                    $this->handshaking($newClient, $line);                    //获取client ip                    socket_getpeername ($newClient, $ip);                    $clients[$ip] = $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";                }            }        }    }    /**     * 握手处理     * @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/websocket/websocket\r\n".            "Sec-WebSocket-Accept:$secAccept\r\n\r\n";        return socket_write($newClient, $upgrade, strlen($upgrade));    }    /**     * 解析接收数据     * @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(){        return socket_close($this->_sockets);    }}$sock = new SocketService();$sock->run();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156

web.html

<!doctype html><html lang="en"> <head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">  <title>websocket</title> </head> <body> <input id="text" value=""> <input type="submit" value="send" onclick="start()"> <input type="submit" value="close" onclick="close()"><div id="msg"></div> <script> /** 0:未连接1:连接成功,可通讯2:正在关闭3:连接已关闭或无法打开*/    //创建一个webSocket 实例    var webSocket  = new  WebSocket("ws://192.168.31.152:8083");    webSocket.onerror = function (event){        onError(event);    };    // 打开websocket    webSocket.onopen = function (event){        onOpen(event);    };    //监听消息    webSocket.onmessage = function (event){        onMessage(event);    };    webSocket.onclose = function (event){        onClose(event);    }    //关闭监听websocket    function onError(event){        document.getElementById("msg").innerHTML = "<p>close</p>";        console.log("error"+event.data);    };    function onOpen(event){        console.log("open:"+sockState());        document.getElementById("msg").innerHTML = "<p>Connect to Service</p>";    };    function onMessage(event){        console.log("onMessage");        document.getElementById("msg").innerHTML += "<p>response:"+event.data+"</p>"    };    function onClose(event){        document.getElementById("msg").innerHTML = "<p>close</p>";        console.log("close:"+sockState());        webSocket.close();    }    function sockState(){        var status = ['未连接','连接成功,可通讯','正在关闭','连接已关闭或无法打开'];            return status[webSocket.readyState];    } function start(event){        console.log(webSocket);        var msg = document.getElementById('text').value;        document.getElementById('text').value = '';        console.log("send:"+sockState());        console.log("msg="+msg);        webSocket.send("msg="+msg);        document.getElementById("msg").innerHTML += "<p>request"+msg+"</p>"    };    function close(event){        webSocket.close();    } </script> </body></html>
原创粉丝点击