费话不多讲,具体看代码
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( [email protected]_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>
时间: 2024-10-11 02:56:06