• websocket服务器+客户端


      1 <?php
      2 $demo = new ws('192.168.90.47',12345);
      3 $demo->run();
      4 
      5 
      6 class ws
      7 {
      8     //当前服务端主连接
      9     private $currentFirstSocket;
     10     //存放客户端socket连接
     11     private $socketList = array();
     12     //存放自定义的客户端连接
     13     private $clientList = array();
     14 
     15 
     16     public function __construct($address, $port)
     17     {
     18         $this->currentFirstSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
     19         socket_set_option($this->currentFirstSocket, SOL_SOCKET, SO_REUSEADDR, 1);
     20         socket_bind($this->currentFirstSocket, $address, $port);
     21         socket_listen($this->currentFirstSocket,2);
     22 
     23         $this->socketList[] = $this->currentFirstSocket;
     24         self::notice('Server Started ...');
     25         self::notice('Listening on   : ' . $address . ' port ' . $port);
     26     }
     27 
     28 
     29     public function run()
     30     {
     31         while (TRUE) {
     32             $connect = $this->socketList;
     33             $write = NULL;
     34             $except = NULL;
     35             self::notice(count($this->socketList) . "  wait to connect ....");
     36             socket_select($connect, $write, $except, NULL);
     37 
     38             foreach ($connect as $currentConnect) {
     39                 self::notice($currentConnect . " into connect");
     40 
     41                 //第一次连接
     42                 if ($currentConnect === $this->currentFirstSocket) {
     43                     $connectSuccessHandle = socket_accept($this->currentFirstSocket);
     44                     $this->socketList[] = $connectSuccessHandle;
     45                     $this->clientList[] = array(
     46                         "handshake" => false,
     47                         "clientHandle" => $connectSuccessHandle
     48                     );
     49                     self::notice($connectSuccessHandle. " new connect success ...");
     50                 } else {
     51                     $currentConnectKey = $this->searchSocketByHandle($currentConnect);
     52                     //第二次接收到的是客户端发送的websocket头协议
     53                     $len = @socket_recv($currentConnect, $buffer, 2048, 0);
     54                     self::notice("len ".$len);
     55                     if ($len < 10) {    //如果接收到的信息长度小于10当作客户端退出
     56                         $this->socketExit($currentConnectKey);
     57                         self::notice($currentConnect . " exit" . "  have:" . count($this->socketList));
     58                         break;
     59                     }
     60                     //检查是否握手,去握手
     61                     if ($this->clientList[$currentConnectKey]['handshake'] === false) {
     62                         self::notice($currentConnect." handshake success...");
     63                         $this->handshake($currentConnectKey, $buffer);
     64                     } else {
     65                         //正式连接,解包客户端的信息
     66                         $buffer = $this->unmask($buffer);
     67                         self::notice($currentConnect." send to server...");
     68 
     69                         $this->send($buffer);
     70                     }
     71                 }
     72             }
     73         }
     74     }
     75 
     76     /*
     77      * 握手
     78      * */
     79     private function handshake($currentConnectKey, $buffer)
     80     {
     81         $buf = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);
     82         $key = trim(substr($buf, 0, strpos($buf, "
    ")));
     83         $new_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
     84         $new_message = "HTTP/1.1 101 Switching Protocols
    ";
     85         $new_message .= "Upgrade: websocket
    ";
     86         $new_message .= "Sec-WebSocket-Version: 13
    ";
     87         $new_message .= "Connection: Upgrade
    ";
     88         $new_message .= "Sec-WebSocket-Accept: " . $new_key . "
    
    ";
     89 
     90         socket_write($this->clientList[$currentConnectKey]['clientHandle'], $new_message, strlen($new_message));
     91         $this->clientList[$currentConnectKey]['handshake'] = true;
     92     }
     93 
     94     /*
     95      * 客户端退出处理
     96      * */
     97     private function socketExit($currentConnectKey)
     98     {
     99         $currentSocket = $this->clientList[$currentConnectKey]['clientHandle'];
    100         socket_shutdown($currentSocket);
    101         socket_close($currentSocket);
    102         foreach ($this->socketList as $key => $val) {
    103             if ($val === $currentSocket) {
    104                 self::notice("delete " . $this->socketList[$key]);
    105                 unset($this->socketList[$key]);
    106             }
    107         }
    108         unset($this->clientList[$currentConnectKey]);
    109     }
    110 
    111     /*
    112      * 发送信息给所有客户端
    113      * */
    114     private function send($sendMsg)
    115     {
    116         $sendMsg = $this->mask($sendMsg);
    117         foreach ($this->clientList as $val) {
    118             self::notice("write to " . $val['clientHandle'] . " " . $sendMsg);
    119             socket_write($val['clientHandle'], $sendMsg, strlen($sendMsg));
    120         }
    121     }
    122 
    123     /*
    124      * 解包客户端发送的信息
    125      * */
    126     function unmask($text)
    127     {
    128         $length = ord($text[1]) & 127;
    129         if ($length == 126) {
    130             $masks = substr($text, 4, 4);
    131             $data = substr($text, 8);
    132         } elseif ($length == 127) {
    133             $masks = substr($text, 10, 4);
    134             $data = substr($text, 14);
    135         } else {
    136             $masks = substr($text, 2, 4);
    137             $data = substr($text, 6);
    138         }
    139         $text = "";
    140         for ($i = 0; $i < strlen($data); ++$i) {
    141             $text .= $data[$i] ^ $masks[$i % 4];
    142         }
    143         return $text;
    144     }
    145     /*
    146      * 封包信息发送给客户端
    147      * */
    148     function mask($text)
    149     {
    150         $b1 = 0x80 | (0x1 & 0x0f);
    151         $length = strlen($text);
    152 
    153         if ($length <= 125)
    154             $header = pack('CC', $b1, $length);
    155         elseif ($length > 125 && $length < 65536)
    156             $header = pack('CCn', $b1, 126, $length);
    157         elseif ($length >= 65536)
    158             $header = pack('CCNN', $b1, 127, $length);
    159         return $header . $text;
    160     }
    161 
    162     private function searchSocketByHandle($handle)
    163     {
    164         foreach ($this->clientList as $key => $value) {
    165             if ($value['clientHandle'] === $handle) {
    166                 return $key;
    167             }
    168         }
    169         return false;
    170     }
    171 
    172     private static function notice($message, $num = 1)
    173     {
    174         echo date("H:i:s") . "  " . $message;
    175         echo str_repeat("
    ", $num);
    176     }
    177 }

    客户端

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>client</title>
        <script src="bootstrap/js/jq.js"></script>
        <script>
            var socket;
            $(document).ready(function(e) {
                connect();
            });
    
    
            function connect(){
                var url='ws://192.168.174.132:12345';
                socket = new WebSocket(url);
                socket.onopen=function(){
                    if(socket.readyState==1){
                        socket.send("hello this is html");
                    }else{
                        console.log("login fail");
                    }
                }
                socket.onmessage=function(msg){
                    console.log(msg);
                }
    
                socket.onclose=function(){
                    console.log("close");
                }
            }
    
            function sendMsg()
            {
                var contetent = $("#test").val();
                console.log("send: "+contetent);
                socket.send(contetent);
            }
    
    
        </script>
    </head>
    <body>
    
    <input type="input" id="test">
    <input type="button" onclick="sendMsg()" value="send">
    
    </body>
    </html>
  • 相关阅读:
    又来项目了,星座运势widget
    ubuntu下编译android源代码
    Android UI,界面辅助设置工具,可随意拖动控件,比google官方提供的方便
    Android 1.5原生软件开发SDK公布
    REST转自WIKI
    Android SDK 1.5 包装索引
    android google market FreshFace上线了,大家都试用试用,反正免费的
    JSON
    ubuntu命令
    网站支付宝接口错误代码:TRADE_DATA_MATCH_ERROR怎么处理? uz
  • 原文地址:https://www.cnblogs.com/hanyouchun/p/4921256.html
Copyright © 2020-2023  润新知