基于swoole的聊天室模型
client.html:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/> <title>聊天室</title> <script src="https://code.jquery.com/jquery-1.11.3.js" type="text/javascript"></script> <script src="swoole.js" type="text/javascript"></script> <style> body { padding: 0; margin: 0; font-size: 12px; } div.form { width: 100%; border: 1px solid #abc; } ul.body { width: 100%; } ul.body li { clear: both; width: 100%; line-height: 2em; } </style> </head> <body> <div class="form"> <input type="text" id="msg" size="100"> <input type="button" id="send" value="waiting"> </div> <ul class="body"> </ul> </body> </html>
swoole.js
var cSetting = { ip: '192.168.1.11', port: 5002 //这儿的端口要与下面swoole.php中的端口相同,且要在防火墙中打开此端口。 }; var chat = { Socket: null, init: function () { var self = this; self.Socket = new WebSocket('ws://' + cSetting.ip + ':' + cSetting.port); self.Socket.onopen = function (e) { if (self.Socket.readyState != 1) return; $('input#send').val('Send'); self.Socket.send('hello'); }; self.Socket.error = function (e) { self.Socket = false; }; self.Socket.onclose = function (e) { self.print('断网啦'); self.Socket = false; }; self.Socket.onmessage = function (request) { self.print(request.data); }; }, send: function ($val) { if (this.Socket == null)this.init(); if (!this.Socket)return; this.Socket.send($val); }, close: function () { if (!this.Socket)return; this.Socket.close(); }, print: function ($str) { $('ul.body').append('<li>' + $str + '</li>'); } }; $(function () { chat.init(); $('input#send').on('click', function () { var input = $('input#msg'); chat.send(input.val()); input.val(''); }); $(window).bind('beforeunload', function () { chat.close(); }); });
swoole.php 【在linux中以cli运行:例:php -f /home/test/swoole.php 】
<?php service(5002); function service($port = 9501) { $setting = [ 'user' => 'www', //子进程运行用户名 'group' => 'www', //子进程运行用户名所在组 // 'daemonize' => 1, //守护进程化。 'log_file' => __DIR__ . '/log1.log', //指定swoole错误日志文件。 'max_conn' => 10000, //最大允许的连接数, 'reactor_num' => 4, //线程数,为CPU核数的1-4倍,建议2倍,最大不得超过CPU核数*4。 'worker_num' => 4, //进程数。 'max_request' => 50,//每个进程的最大任务数 'task_worker_num' => 2, //配置task进程的数量,配置此参数后将会启用task功能。所以swoole_server务必要注册onTask/onFinish2个事件回调函数。如果没有注册,服务器程序将无法启动。, 'task_ipc_mode' => 1, //设置task进程与worker进程之间通信的方式,1, 使用unix socket通信 2, 使用消息队列通信 3, 使用消息队列通信,并设置为争抢模式 设置为3后,task/taskwait将无法指定目标进程ID 'task_max_request' => 0, //设置task进程的最大任务数, 'task_tmpdir' => __DIR__ . '/', //设置task的数据临时目录 'discard_timeout_request' => true, //丢弃已失联进程收到的数据请求 'backlog' => 128, //listen backlog ]; $socket = new swoole_websocket_server("0.0.0.0", $port); $socket->addlistener('0.0.0.0', $port + 1, SWOOLE_SOCK_TCP); $socket->set($setting); $socket->on('start', function (swoole_websocket_server $server) { echo "Service:\n================================\n"; print_r(['master_pid' => $server->master_pid, 'manager_pid' => $server->manager_pid]); }); $socket->on('open', function (swoole_websocket_server $server, swoole_http_request $request) { echo "open:" . print_r($request, true) . "\n"; }); $socket->on('message', function (swoole_websocket_server $server, $request) { echo "message:" . print_r($request, true) . "\n"; $val = $request->data; $id = $request->fd; if (substr($val, 0, 4) === 'send') { var_dump($server->send($id, '【' . date('H:i:s') . '】Message Send: ' . $val)); } else if (substr($val, 0, 4) === 'task') { $server->push($id, '【' . date('H:i:s') . '】Message Push: ' . $val . '[' . mt_rand() . ']'); $server->task([$id, $val]); } else { $server->push($id, '【' . date('H:i:s') . '】Message Push: ' . $val . '[' . mt_rand() . ']'); } }); $socket->on('task', function (swoole_websocket_server $server, $task_id, $from_id, $key) { echo "task:" . "\t taskID={$task_id}\t fromID={$from_id}\n" . print_r($key, true); sleep(1); $server->push($key[0], '后台回复:' . $key[1]); $server->finish($key[0]); }); $socket->on('finish', function (swoole_websocket_server $server, $task_id, $data) { echo "Finish taskID={$task_id}\n"; }); $socket->on('close', function (swoole_websocket_server $server, $fd) { echo "close:" . print_r($fd, true) . "\n"; }); $socket->start(); }