php websoket 通讯

server

<?php 
/**
 * websorket 即时通讯服务器
 */

class Websocket
{
    private $_serv;
    private $_pdo;
public function __construct($host='0.0.0.0',$port=9501)
    {
        $this->_serv=new swoole_websocket_server($host, $port, SWOOLE_BASE);
        $this->_pdo=new PDO("mysql:host=*********;dbname=leocms", "*****","*****"); //初始化一个PDO对象$this->_serv->set(
            ['websocket_compression' => true,]
            );
        $this->_serv->on('handshake',[$this,'on_handshake']);
        $this->_serv->on('open',[$this,'on_open']);
        $this->_serv->on('message',[$this,'on_message']);
        $this->_serv->on('close',[$this,'on_close']);
    }
    /**
     * 退出登录
     */
    public function on_close(swoole_websocket_server $_serv,$fd)
    {
        echo "connection close: {$fd}\n";
        //增加用户
        echo $sql="update users set is_online=0,sec_websocket_key=null,fd=0 where fd=?";
        $prepare_obj=$this->_pdo->prepare($sql);
        $prepare_obj->execute([$fd]);
        //查询所有在线用户
            $sql="select * from users where is_online=1 and fd>0";
            $prepare_obj=$this->_pdo->prepare($sql);
            $prepare_obj->execute();
            $onlist=$prepare_obj->fetchall();
            //向客户端发送在线用户
            foreach($_serv->connection_list() as $key =>$val){
            
            $_serv->push($val,json_encode(['type'=>1,'onlist'=>$onlist]));
           
            }
    }
    /**
     * 握手函数
     */
    public function on_handshake(swoole_http_request $request, swoole_http_response $response)
    {
        $openid=$request->get['openid'];
        $sql="select * from users where openid=?";
        $prepare=$this->_pdo->prepare($sql);
        $prepare->execute([$openid]);
        $one=$prepare->fetch();
        if(empty($one)){
            $response->end();
            return false;
        }
        // if (如果不满足我某些自定义的需求条件,那么返回end输出,返回false,握手失败) {
        //    $response->end();
        //     return false;
        // }

      // websocket握手连接算法验证
        $secWebSocketKey = $request->header['sec-websocket-key'];
        $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
        if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
            $response->end();
            return false;
        }
        $key = base64_encode(sha1(
            $request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
            true
        ));

        $headers = [
            'Upgrade' => 'websocket',
            'Connection' => 'Upgrade',
            'Sec-WebSocket-Accept' => $key,
            'Sec-WebSocket-Version' => '13',
        ];

      // Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
        if (isset($request->header['sec-websocket-protocol'])) {
            $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
        }

        foreach ($headers as $key => $val) {
            $response->header($key, $val);
        }

        //修改用户用户
        $sql="update users set is_online=1,sec_websocket_key=?,fd=? where openid=?";
        $prepare_obj=$this->_pdo->prepare($sql);
        $prepare_obj->execute([$secWebSocketKey,$request->fd,$openid]);
        $response->status(101);
        $response->end();
    }
    /**
     * WebSocket客户端与服务器建立连接并完成握手后会回调此函数
     */
    public function on_open(swoole_websocket_server $_serv, swoole_http_request $request)
    {
        echo "server#{$_server->worker_pid}: handshake success with fd#{$request->fd}\n";
        var_dump($_serv->exist($request->fd), $_serv->getClientInfo($request->fd));
        $fd = $request->fd;
    
    }
    /**
     * WebSocket客户端与服务器建立连接并完成握手后会回调此函数
     */
    public function on_message(swoole_websocket_server $_serv, $frame)
    {
        $data = json_decode($frame->data , true);
        if($data['type']=='1'){
            //查询所有在线用户
            $sql="select * from users where is_online=1 and fd>0";
            $prepare_obj=$this->_pdo->prepare($sql);
            $prepare_obj->execute();
            $onlist=$prepare_obj->fetchall();
            //向客户端发送在线用户
            foreach($_serv->connection_list() as $key =>$val){
            
            $_serv->push($val,json_encode(['type'=>1,'onlist'=>$onlist]));
           
            }
        }
        if ($data['type']=='2') {
            // //匿名群聊
            foreach($_serv->connection_list() as $key =>$val){
                echo  $val; 
                $_serv->push($val,json_encode(['type'=>2,'msg'=>'你好 世界']));
               
            }
        }
        if($data['type']=='3')
        {
            echo $openid=$data['openid'];
            $sql="select * from users where openid=? and is_online=1";
            $prepare_obj=$this->_pdo->prepare($sql);
            $ones=$prepare_obj->execute([$openid]);
            $ones=$prepare_obj->fetch();
            var_dump($ones);
            $_serv->push($ones['fd'],json_encode(['type'=>3,'msg'=>$data['msg']]));
        }                           
    }
    /**
     * 开启服务器
     */
    public function start_server()
    {
        return $this->_serv->start();
    }
}
$server=new Websocket('0.0.0.0',9502);
$server->start_server();

 client

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>即时通讯系统</title>
<link rel="stylesheet" href="css/style.css" media="screen" type="text/css" />
</head>
<body>
<div id="convo">
   <div class="denglu">
        登录用户id:<input type="text" name="user" >
       <button class="login">登录</button>
   </div>
   
    <ul  class="chat-thread">  
    </ul>       
    <!--聊天框-->
    <div class="chat-window">
        <input class="chat-window-message" name="chat-window-message" autocomplete="on" placeholder="请输入内容按回车键发送" type="text" value="123">
    </div>
     <button class="loguot">退出</button> 
    <!--在线用户-->
    <h1>在线用户</h1>
     <ul class="user-thread">  
    </ul>
     <div class="chat-window-dan">
        <input class="chat-window-message-2" name="chat-window-message-2" autocomplete="on" placeholder="请输入内容按回车键发送" type="text"  value="123" data-openid="">
    </div>

</div>
  <!--引入jq文件-->
 <script src='http://libs.baidu.com/jquery/1.9.1/jquery.min.js'></script>
 <script type="text/javascript">
    $(document).on('click', '.zhiidng', function() {
       $(".chat-window-dan").show();
       $(".chat-window-message-2").attr({'data-openid':$(this).attr('data-openid')})

    });
    $('.login').on('click' , function(){
        openid = $('[name=user]').val().trim();
        if(openid ==''){
            alert('请先登录');
        }else{
            socketlogin(openid);
        }
    })
    
    var socket;
    $('.loguot').on('click' , function(){
        socket.close();
         $(".denglu").show();
         $('[name=user]').val('')
    })
    function socketlogin(openid){
        socket=new WebSocket('ws://********:9502?openid=' + openid);
        socket.onopen=function()
        {
            socket.send(setMsg(1,'用户'+openid+"你好",openid));
            $(".denglu").hide();
            console.log('连接成功');
        }
        socket.onmessage=function(e)
        {
           console.log('接收数据');
           var datas= eval('('+e.data+')');
           if(datas.type==1){
            var strs=''
            
                for (var i = 0; i < datas.onlist.length; i++) {
                    strs+='<li class="left zhiidng" data-fd="'+datas.onlist[i].fd+'" data-openid="'+datas.onlist[i].openid+'">'+datas.onlist[i].username+'</li>'
                }
                console.log(strs)
                $('.user-thread').html(strs);
           }else if(datas.type==2){
            $('.chat-thread').append('<li class="left">'+datas.msg+'</li>');
           }else if(datas.type==3){
            $('.chat-thread').append('<li class="left">'+datas.msg+'</li>');
           }
           // $('.chat-thread').append('<li class="left">'+e.data+'</li>');
        }
        socket.onclose= function()
        {
            $('.chat-thread').append('<li class="left">退出聊天室</li>');
        }    
    }



    $('.chat-window-message').keydown(function(e){
    if(e.keyCode==13){
            var speak=$('.chat-window-message').val();

            $('.chat-thread').append('<li>'+speak+'</li>');
            $('.chat-window-message').val('');
            console.log(socket);
            if(socket.readyState!=1){
                alert('尚未连接');
                return ;
            }
            socket.send(setMsg(2,speak,openid));


    }})
$('.chat-window-message-2').keydown(function(e){
    if(e.keyCode==13){
            var speak=$('.chat-window-message-2').val();
            var openid=$('.chat-window-message-2').attr('data-openid');
            $('.chat-thread').append('<li>'+speak+'</li>');
            $('.chat-window-message-2').val();
            console.log(socket);
            if(socket.readyState!=1){
                alert('尚未连接');
                return ;
            }
            socket.send(setMsg(3,speak,openid));


    }})



   function setMsg(type,msg , openid){
    var msgObject = {
        type:type,
        msg: msg ,
        openid: openid ,
     }
    return JSON.stringify(msgObject);
  }


</script>

猜你喜欢

转载自www.cnblogs.com/leo0362/p/11970344.html