完整版websocket帶數據庫


swoolechat.php

<?php
use Swoole\Coroutine as co;
class swoolechat {
    //協程內部的變量
    public $sql_string=null;
    public $sql_res=null;
    public $map=null;
    //公共變量
    public $ws;
    public $configws=array(
        'worker_num' => 1,//進程數 進程數越多,負載能力越大,建議cpu核數2倍
        'max_request' => 10000,//進程處理完這么多任務數,就會重啟,防止溢出
        'max_conn'=>10000,//最大保持連接數,也就是同時在線人數
        'ipc_mode' => 1,//1使用unix socket通信2使用消息隊列通信3使用消息隊列通信,並設置為爭搶模式
        'dispatch_mode' => 2,//2固定模式,同一個鏈接只被一個worker處理,1輪詢模式3爭搶模式
        'debug_mode'=> 1 ,
        'daemonize' => 0,//守護模式
        'log_file' => '\log\swoole.log',
        'heartbeat_check_interval' => 30,//心跳偵測時間間隔
        'heartbeat_idle_time' => 600,//閑置時間上線
    );
    public $configsql=array(
        'host'=>'127.0.0.1',
        'port'=>3306,
        'user'=>'ws_ltcpi_com',
        'password'=>'La2bKpT4T2xrrkLL',
        'database'=>'ws_ltcpi_com',
        'charset'=>'utf8',
        'timeout'=>10,
    );
    //構造函數
    public function __construct() {
        //創建websocket服務器對象,監聽0.0.0.0:端口
        $this->ws = new swoole_websocket_server("0.0.0.0", 9501);
        $this->ws->set($this->configws);
        //監聽WebSocket連接
        $this->ws->on('open', function ($ws, $request) {
            echo "server: handshake success with fd{$request->fd}\n";
            $this->ws->push($request->fd, "hello, welcome\n");
        });
        //監聽WebSocket收到信息
        $this->ws->on('message', function ($ws, $frame) {
//            echo "onmessage: handshake success with fd{$frame}\n";
            self::onmessage($ws,$frame->fd,$frame->data);
        });
        //關閉事件
        $this->ws->on('close', function ($ws, $fd) {
            echo "client-{$fd} is closed\n";
        });
        //啟動服務
        echo "啟動3服務\n";
        $this->ws->start();
    }
    //內部方法
    protected function get_sql_insert($table,$arr){
        $sql=" insert into ".$table." (";
        foreach (array_keys($arr) as $k=>$v){
            $sql.=$v.',';
        }
        $sql=rtrim($sql, ",");
        $sql.=') values (';
        foreach ($arr as $k=>$v){
            $sql.="'".$v."',";
        }
        $sql=rtrim($sql, ",");
        $sql.=')';
        return $sql;
    }
    protected function get_sql_delete_fd($fd){
        $res="DELETE FROM fa_fdband WHERE fd = '{$fd}'";
        return $res;
    }
    protected function get_sql_delete_userid($userid){
        $res="DELETE FROM fa_fdband WHERE userid = '{$userid}'";
        return $res;
    }
    protected function pushtofd($fd,$type,$status,$msg){
        $res=json_encode(array('type'=>$type,'status'=>$status,'msg'=>$msg));
        $this->ws->push($fd,utf8_encode($res));
    }
    protected function get_sql_bandlist($fd){
        $sql="select * from fa_fdband where fd='{$fd}'order by id desc";
        return $sql;
    }
    //收到命令
    public function onmessage($ws,$fd,$data){
        //獲取fd  數組數據
        $data_arr=json_decode($data, true);
        if ($data=='heart' or array_key_exists('type',$data_arr)==false){
            //心跳回復
            $ws->push($fd,'heart');
        }else{
            $type=$data_arr['type'];
            //登錄房間
            if ($type=='band'){
                $roomid=$data_arr['roomid'];
                $userid=$data_arr['userid'];
                self::band($fd,$roomid,$userid);
            }
            //聊天
            if ($type=='chatsend'){
                $msg=$data_arr['msg'];
                self::chatsend($fd,$msg);
            }
        }
    }
    //綁定房間
    public function band($fd,$roomid,$userid){
        //生成刪除語句  插入語句
        $this->map=array(
            'fd'=>$fd,
            'userid'=>$userid,
            'roomid'=>$roomid,
            'createtime'=>time(),
        );
        go(function() {
            $db=new co\MySQL();
            $db->connect($this->configsql);
            //獲取變量
            $fd=$this->map['fd'];
            $roomid=$this->map['roomid'];
            $userid=$this->map['userid'];
            //刪除同fd房間
            $res=$db->query(self::get_sql_delete_fd($fd));
            var_dump(self::get_sql_delete_fd($fd));
            var_dump($res);
            if ($res!=1){
                self::pushtofd($fd,'band',0,'登錄房間失敗,刪除同fd失敗');
            }
            //刪除同userid綁定信息
            $res=$db->query(self::get_sql_delete_userid($userid));
            if ($res!=1){
                self::pushtofd($fd,'band',0,'登錄房間失敗,刪除同userid失敗');
            }
            //創建房間
            $res=$db->query(self::get_sql_insert('fa_fdband',$this->map));
            if ($res==1){
                self::pushtofd($this->map['fd'],'band',1,'登錄房間成功');
            }else{
                self::pushtofd($this->map['fd'],'band',0,'登錄房間失敗,因為插入失敗');
            }
        });
    }

    public function chatsend($fd,$msg){
        $this->map=array(
            'fd'=>$fd,
            'msg'=>$msg,
        );
        go(function() {
            $db=new co\MySQL();
            $db->connect($this->configsql);
            //獲取變量
            $fd=$this->map['fd'];
            $msg=$this->map['msg'];
            //根據fd查詢綁定信息
            $band_list=$db->query(self::get_sql_bandlist($fd));
            if (count($band_list)<1){
                self::pushtofd($this->map['fd'],'chatsend',0,'請先綁定房間');
                return;
            }
            //保存記錄
            $map=array(
                'userid'=>$band_list[0]['userid'],
                'roomid'=>$band_list[0]['roomid'],
                'msg'=>$msg,
                'createtime'=>time(),
            );
            //生成保存消息語3句
            $res=$db->query(self::get_sql_insert('fa_fdchat',$map));
            var_dump(self::get_sql_insert('fa_fdchat',$map));
            var_dump($res);
            self::pushtofd($this->map['fd'],'chatsend',1,'success');
            //轉發消息
            $band_list=$db->query("select * from fa_fdband where roomid='{$map['roomid']}'order by id desc");
            foreach ($band_list as $k=>$v){
                if ($v['fd']==$fd){
                    $msg=array(
                        'nickname'=>'我',
                        'msg'=>$map['msg']
                    );
                    self::pushtofd($v['fd'],'chatrev',1,$msg);
                }else{
                    $msg=array(
                        'nickname'=>'追風少年',
                        'msg'=>$map['msg']
                    );
                    self::pushtofd($v['fd'],'chatrev',1,$msg);
                }
            }
        });
    }
}
$obj=new SwooleChat();

client.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webSocket客戶端接收命令</title>
</head>
<body>
<p id="status"></p>
<input type="text" id="login" style="width: 500px"  value='{"type":"band","roomid":"3","userid":"4"}'/>
<button onclick="login()">綁定房間</button>
<br/>
<input type="text" id="chat" style="width: 500px"  value='{"type":"chatsend","msg":"大家好我是新人4"}'/>
<button onclick="chat()">發送消息</button>
<!--<button onclick="clientClose()">關閉連接</button>-->
<!--<button onclick="clientBreak()">徹底斷開</button>-->
<script type="text/javascript">
    var lockReconnect = false;//避免重復連接
    var wsUrl = "ws://124.156.153.202:9501";		// websocket鏈接
    var ws;
    function decodeUnicode(str) {
        str = str.replace(/\\/g, "%");
        return unescape(str);
    }

    createWebSocket();
    // 創建websocket
    function createWebSocket(){
        try {
            ws = new WebSocket(wsUrl);
            ws.onopen = function (evt) {
                onOpen(evt);
            };
            ws.onclose = function (evt) {
                onClose(evt);
                websocketReconnect(wsUrl);
            };
            // 接收服務端數據時觸發事件
            ws.onmessage = function (evt) {
                onMessage(evt);
            };
            // 通信發生錯誤時觸發
            ws.onerror = function (evt) {
                websocketReconnect(wsUrl);
                onError(evt);
            };
        } catch (e) {
            console.log('catch');
            websocketReconnect(wsUrl);
        }
    }
    //被動業務
    function onOpen(evt) {
        document.getElementById('status').innerText += "receive:" + "建立鏈接成功..." + "\n";
        //心跳檢測重置
        heartCheck.start();
    }
    function onClose(evt) {
        document.getElementById('status').innerText += "receive:" + "連接已關閉..." + "\n";
    }
    function onMessage(evt) {
        if (evt.data!=='heart'){

            document.getElementById('status').innerText += "receive:" + decodeUnicode(evt.data)+ "\n";
        }
        heartCheck.start();
    }
    function onError(evt) {
        document.getElementById('status').innerText += "通信錯誤"+ "\n";
    }
    //重新連接
    function websocketReconnect(url) {
        if (lockReconnect) {       // 是否已經執行重連
            return;
        }else {
            lockReconnect = true;
            //沒連接上會一直重連,設置延遲避免請求過多
            tt && clearTimeout(tt);
            var tt = setTimeout(function () {
                createWebSocket(url);
                lockReconnect = false;
            }, 5000);
        }
    }
    //發送心跳
    var heartCheck = {
        timeout: 5000,
        timeoutObj: null,
        serverTimeoutObj: null,
        start: function () {
            var self = this;
            this.timeoutObj && clearTimeout(this.timeoutObj);
            this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
            this.timeoutObj = setTimeout(function () {
                ws.send("heart");
                console.log('send:start');
                self.serverTimeoutObj = setTimeout(function () {
                    ws.close();
                }, self.timeout);
            }, this.timeout)
        }
    };
    //主動業務
    function login() {
        ws.send(document.getElementById('login').value);
    }
    function chat() {
        ws.send(document.getElementById('chat').value);
    }

    function clientClose() {
        ws.close();
        document.getElementById('status').innerText += "客戶端主動普通斷開" +"\n";
    }

</script>
</body>
</html>

sql

https://files.cnblogs.com/files/bufeetu/websocket.7z


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM