PHP SOCKE实现聊天系统

费话不多讲,具体看代码

 1.服务端实现

class Ws{
    
    private $host = '127.0.0.1';
    private $port = 8080;
    private $maxuser = 10;
    private $socket;
    public $accept = [];
    private $isHand = [];
    private $cycle = [];
    public function __construct($host,$port,$maxuser)
    {
        $this->host = $host;
        $this->port = $port;
        $this->maxuser = $maxuser;
    }
    
    public  function start()
    {
        // 创建一个Socket
        $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
         //允许使用本地地址        
        socket_set_option($this->socket,SOL_SOCKET,SO_REUSEADDR,TRUE);
        // 绑定地址和端口
        socket_bind($this->socket,$this->host,$this->port);
        //侦听
        socket_listen($this->socket,$this->maxuser);
        while(True){
            $this->cycle = $this->accept;
            $this->cycle[] = $this->socket;
            //阻塞用,有新连接时才会结束
            socket_select($this->cycle, $write, $except, null);
            //轮询
            foreach($this->cycle as $key =>$v){
                
                if($v === $this->socket){
                    //当接受一个Socket不成功时,继续下一个
                    if(($accept = socket_accept($v))<0){
                        continue;
                    }
                    //添加到循环池
                    $this->add_accept($accept);
                    continue;
                }
                
                // 获得当前连接健值 
                $index = array_search($v,$this->accept);
                
                if($index === null){
                    continue;
                }
                
                // 接受客户端数据
                if( !@socket_recv($v,$data,1024,0) || !$data){
                    
                    $this->close($v);
                    continue;
                }
                
                // 握手并发送用户连接数
                if(!$this->isHand[$index]){
                    $this->upgrade($v,$data,$index);
                    call_user_func_array('user_add_callback',array($this));
                    continue;
                }
                $data = $this->decode($data);
                // 发送数据
                call_user_func_array('send_callback', array($data, $index, $this));
            }    
            sleep(1);    
        }    
            
        
    }

回调

  function send_callback($data, $index, $ws) {
    $data = json_encode(array(
                        'text' => $data,
                        'user' => $index,
                        ));
    send_to_all($data, 'text', $ws);
}

function send_to_all($data, $type, $ws){
    $res = array(
            'msg' => $data,
            'type' => $type,
            );
    $res = json_encode($res);
    $res = $ws->frame($res);
    print_r($ws->accept);
    foreach ($ws->accept as $key => $value) {
        socket_write($value, $res, strlen($res));
    }
}

function close_callback($ws) {
    $data = count($ws->accept);
    send_to_all($data, 'num', $ws);
}

function user_add_callback($ws) {
    $data = count($ws->accept);
     send_to_all($data, 'num', $ws);
}

 

 

 

 

客户端实现

<!DOCTYPE html>
<html dir="ltr" lang="zh" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>websocket聊天室</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">

</head>
<body>
<div class="container">
    <p>在线人数<span id="userNum"></span></p>
    <textarea id="message" rows="10"></textarea>
    <div class="send">
        <p><textarea id="input" placeholder="请输入要发送的内容"></textarea></p>
        <p><button type="button" class="btn btn-primary" id="sub">发送</button></p>
    </div>
</div>
<script type="text/javascript">
(function(){
    var $ = function(id){return document.getElementById(id) || null;}
    var wsServer = 'ws://127.0.0.1:8080'; 
    var ws = new WebSocket(wsServer);
    var isConnect = false;
    ws.onopen = function (evt) { onOpen(evt) }; 
    ws.onclose = function (evt) { onClose(evt) }; 
    ws.onmessage = function (evt) { onMessage(evt) }; 
    ws.onerror = function (evt) { onError(evt) }; 
    function onOpen(evt) { 
        console.log("连接服务器成功");
        isConnect = true;
    } 
    function onClose(evt) { 
        //console.log("Disconnected"); 
    } 
    function onMessage(evt) {
        var data = JSON.parse(evt.data);
        switch (data.type) {
            case 'text':
                addMsg(data.msg);
                break;
            case 'num' :
                updataUserNum(data.msg);
                break;
        }
        
        console.log('Retrieved data from server: ' + evt.data);
    }
    function onError(evt) { 
        //console.log('Error occured: ' + evt.data); 
    }
    function sendMsg() {
        if(isConnect){
            ws.send($('input').value);
            $('input').value = '';
        }
    }
    function addMsg(msg) {
        msg = JSON.parse(msg);
        var text = '用户' + msg.user + '说:\n' + msg.text + '\n';
        $('message').value += text;
        $('message').scrollTop = $('message').scrollHeight;
    }
    function updataUserNum(msg) {
        $('userNum').innerText = msg;
    }
    $('sub').addEventListener('click',sendMsg,false);
})();
</script>
</body>
</html>

 

posted @ 2016-07-09 21:14  拼搏的豆子  阅读(401)  评论(0编辑  收藏  举报