commit 1be654dd5faaa5291602a30dbcc428cee040fc45 Author: Wenbin.Wang Date: Fri Dec 24 16:44:53 2021 +0800 代码 diff --git a/Client/tcp_client.php b/Client/tcp_client.php new file mode 100644 index 0000000..8960867 --- /dev/null +++ b/Client/tcp_client.php @@ -0,0 +1,23 @@ +connect('127.0.0.1', 9501)) { + echo 'Connection fail!'; + exit(); +} + +// 接收控制台输入的消息 +fwrite(STDOUT, 'Please send your name: '); +$message = trim(fgets(STDIN)); + +// 发送消息给TCP服务器 +if (!$client->send($message)) { + echo 'Send fail!'; + exit(); +} + +// 接收TCP服务器返回的数据并显示 +$resule = $client->recv(); +echo $resule; \ No newline at end of file diff --git a/Client/udp_client.php b/Client/udp_client.php new file mode 100644 index 0000000..36f72a1 --- /dev/null +++ b/Client/udp_client.php @@ -0,0 +1,23 @@ +connect('127.0.0.1', 9502)) { + echo 'Connection fail!'; + exit(); +} + +// 接收控制台输入的消息 +fwrite(STDOUT, 'Please send your name: '); +$message = trim(fgets(STDIN)); + +// 发送消息给TCP服务器 +if (!$client->send($message)) { + echo 'Send fail!'; + exit(); +} + +// 接收TCP服务器返回的数据并显示 +$resule = $client->recv(); +echo $resule; \ No newline at end of file diff --git a/Script/Reload.sh b/Script/Reload.sh new file mode 100644 index 0000000..9d85c20 --- /dev/null +++ b/Script/Reload.sh @@ -0,0 +1,4 @@ +pid=`pidof http_server` +echo "The http server pid is ${pid}" +kill -USR1 $pid +echo "Reloading success" \ No newline at end of file diff --git a/Server/http.php b/Server/http.php new file mode 100644 index 0000000..5ef214c --- /dev/null +++ b/Server/http.php @@ -0,0 +1,186 @@ +server = new Swoole\Http\Server(self::HOST, self::PORT); + + // 设置响应html文件模式以及定义路径 + $this->server->set([ + 'worker_num' => 2, + 'enable_static_handler' => true, + 'document_root' => dirname(dirname(__FILE__)) . '/Template' + ]); + + // 设置异步AIO线程数量 + swoole_async_set([ + 'thread_num' => 10, + ]); + + // 监听启动 + $this->server->on('Start', [$this, 'onStart']); + // 监听请求并输出内容 + $this->server->on('Request', [$this, 'onRequest']); + } + + /** + * 监听启动,修改主进程名称,便于执行平滑重启 + */ + public function onStart() + { + swoole_set_process_name('http_server'); + } + + /** + * 监听请求并输出内容 + * @param $request object 请求对象 + * @param $response object 响应对象 + */ + public function onRequest($request, $response) + { + // 优化请求,防止图标再次请求浪费资源 + if ($request->server['request_uri'] == '/favicon.ico') { + $response->status(404); + $response->end(); + return ; + } + + $get = json_encode($request->get); + $html = <<Hello Swoole. +

The get request is {$get}

+EOT; + + // 记录访问日志 + $log = [ + 'time' => date('Y-m-d H:i:s'), + 'get' => $request->get, + 'post' => $request->post, + 'header' => $request->header + ]; + + if (!is_dir(__DIR__ . '/log')) { + mkdir(__DIR__ . '/log'); + } + + Swoole\Async::writeFile(__DIR__ . '/log/access.log', json_encode($log) . PHP_EOL, function($filename) {}, FILE_APPEND); + + // 在MySQL数据库中增加访问量 + $this->addReadNum(); + + // 读取redis里的访问量数据,如无则从常量中定义 + $this->getReadNum(); + + // 设置响应头信息 + $response->header('Content-Type', 'text/html; charset=utf-8'); + // 设置cookie信息 + $response->cookie('code', 'Hello world', time() + 1800); + // 输出显示内容 + $response->end($html); + } + + /** + * 增加访问量方法 + */ + public function addReadNum() + { + $update_db = new Swoole\Coroutine\MySQL(); + $select_db = new Swoole\Coroutine\MySQL(); + $config = [ + 'host' => '127.0.0.1', + 'port' => 3306, + 'user' => 'swoole', + 'password' => 'Zhang1994)!)(', + 'database' => 'swoole', + 'charset' => 'utf8mb4', + 'timeout' => 2 + ]; + + // 进行MySQL数据库连接 + $conn_res = $select_db->connect($config); + + if ($conn_res === false) { + echo 'MySQL connect error!' . PHP_EOL; + var_dump($select_db->connect_errno, $select_db->connect_error) . PHP_EOL; + throw new Swoole\ExitException('program exit.'); + } + + // 获取到访问量的数据 + $result = $select_db->query('SELECT read_num FROM test WHERE id = 1'); + + if ($result !== false) { + if (isset($result[0]['read_num'])) $this->read_num = $result[0]['read_num']; + echo 'MySQL execute success, data: ' . PHP_EOL; + var_dump($result); + } + + // 一定要记得关闭MySQL连接 + $select_db->close(); + + // 进行MySQL数据库连接,这里是并发再开启一个MySQL连接进程 + $conn_res = $update_db->connect($config); + + if ($conn_res === false) { + echo 'MySQL connect error!' . PHP_EOL; + var_dump($update_db->connect_errno, $update_db->connect_error) . PHP_EOL; + throw new Swoole\ExitException('program exit.'); + } + + // 执行增加访问量的语句并处理结果 + $result = $update_db->query('UPDATE test SET read_num = read_num + 1 WHERE id = 1'); + + if ($result !== false) { + echo 'MySQL execute success, affected rows: ' . $update_db->affected_rows . ', insert id: ' . $update_db->insert_id . PHP_EOL; + } + + // 一定要记得关闭MySQL连接 + $update_db->close(); + } + + /** + * 读取redis里的访问量数据,如无则从常量中定义 + */ + public function getReadNum() + { + $redis = new Swoole\Coroutine\Redis(); + $redis->connect('127.0.0.1', 6379); + $read_num = $redis->get('read_num'); + + if (empty($read_num)) { + if (!isset($this->read_num)) { + throw new Swoole\ExitException('Read num not exist!'); + } + + $read_num = $this->read_num; + $redis->set('read_num', $read_num); + echo 'The data from MySQL.' . PHP_EOL; + } else { + echo 'The data from Redis.' . PHP_EOL; + } + + echo "The redis read num is: {$read_num}"; + } + + /** + * 启动Http服务器 + */ + public function start() + { + $this->server->start(); + } +} + +$http = new Http(); +$http->start(); \ No newline at end of file diff --git a/Server/process.php b/Server/process.php new file mode 100644 index 0000000..6160445 --- /dev/null +++ b/Server/process.php @@ -0,0 +1,58 @@ +job($i); + // 把结果写入管道 + $worker->write($res); + }, true); + // 启动进程,返回进程号 + $pid = $process->start(); + $this->worker[$pid] = $process; + } + + // 显示主程序结束时间 + echo 'process-end-time:' . date('Y-m-d H:i:s') . PHP_EOL; + } + + /** + * 显示进程结果 + */ + public function getChannelResponse() + { + foreach ($this->worker as $worker) { + // 通过读取每个管道中的结果来进行显示 + echo $worker->read(); + } + } + + /** + * 进程工作逻辑,模拟耗时1s的任务 + * @param int $i + * @return string + */ + protected function job(int $i) + { + sleep(1); + return "job {$i} success" . PHP_EOL; + } +} + +$pro = new process(); +$pro->doJob(); +$pro->getChannelResponse(); \ No newline at end of file diff --git a/Server/table.php b/Server/table.php new file mode 100644 index 0000000..b3ee652 --- /dev/null +++ b/Server/table.php @@ -0,0 +1,50 @@ +column('id', $table::TYPE_INT, 4); + $table->column('name', $table::TYPE_STRING, 10); + $table->column('age', $table::TYPE_INT, 4); + + // 创建表 + $table->create(); + + // 设置方式1 + $table['human1'] = [ + 'id' => 1, + 'name' => 'neo', + 'age' => 30 + ]; + + // 设置方式2 + $table->set('human2', [ + 'id' => 2, + 'name' => 'jason', + 'age' => 28 + ]); + + // 值自增 + $table->incr('human1', 'age', 1); + // 值自减 + $table->decr('human2', 'age', 2); + + var_dump($table['human1']); + var_dump($table->get('human2')); + + echo 'deleted.' . PHP_EOL; + + // 删除值 + $table->del('human2'); + + var_dump($table->exist('human2')); + } +} + +$table = new table(); +$table->doJob(); \ No newline at end of file diff --git a/Server/tcp.php b/Server/tcp.php new file mode 100644 index 0000000..65e3fa2 --- /dev/null +++ b/Server/tcp.php @@ -0,0 +1,78 @@ +server = new Swoole\Server(self::HOST, self::PORT); + + // 设置TCP服务器参数 + $this->server->set([ + 'worker_num' => self::WORKER_NUM, + 'max_request' => self::MAX_REQUEST + ]); + + // 监听连接进入事件 + $this->server->on('Connect', [$this, 'onConnect']); + // 监听数据接收事件 + $this->server->on('Receive', [$this, 'onReceive']); + // 监听连接关闭事件 + $this->server->on('Close', [$this, 'onClose']); + } + + /** + * 监听连接进入事件 + * @param $serv Swoole\Server TCP对象 + * @param $client_id int 客户端连接ID + * @param $reactor_id int 线程ID + */ + public function onConnect($serv, $client_id, $reactor_id) + { + echo 'Client: Connect.' . PHP_EOL . 'This client id: ' . $client_id . PHP_EOL . 'This reactor id: ' . $reactor_id . PHP_EOL; + } + + /** + * 监听数据接收事件 + * @param $serv Swoole\Server TCP对象 + * @param $client_id int 客户端连接ID + * @param $reactor_id int 线程ID + * @param $data string 客户端传入的字符串 + */ + public function onReceive($serv, $client_id, $reactor_id, $data) + { + $serv->send($client_id, 'This client id: ' . $client_id . PHP_EOL . 'This reactor id: ' . $reactor_id . PHP_EOL . 'Hello ' . $data . '!' . PHP_EOL); + } + + /** + * 监听连接关闭事件 + * @param $serv Swoole\Server TCP对象 + * @param $client_id int 客户端连接ID + */ + public function onClose($serv, $client_id) + { + echo 'Client: Client ' . $client_id . ' close.' . PHP_EOL; + } + + /** + * 启动TCP服务器 + */ + public function start() + { + $this->server->start(); + } +} + +$tcp = new Tcp(); +$tcp->start(); \ No newline at end of file diff --git a/Server/udp.php b/Server/udp.php new file mode 100644 index 0000000..d161a5a --- /dev/null +++ b/Server/udp.php @@ -0,0 +1,53 @@ +server = new Swoole\Server(self::HOST, self::PORT, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); + + // 设置TCP服务器参数 + $this->server->set([ + 'worker_num' => self::WORKER_NUM, + 'max_request' => self::MAX_REQUEST + ]); + + // 监听数据接收事件 + $this->server->on('Packet', [$this, 'onPacket']); + } + + /** + * 监听数据接收事件 + * @param $serv Swoole\Server UDP对象 + * @param $data string 客户端传入的字符串 + * @param $clientInfo array 客户端信息数据 + */ + public function onPacket($serv, $data, $clientInfo) + { + $serv->sendto($clientInfo['address'], $clientInfo['port'], 'Hello ' . $data . '!' . PHP_EOL); + var_dump($clientInfo); + } + + /** + * 启动UDP服务器 + */ + public function start() + { + $this->server->start(); + } +} + +$udp = new Udp(); +$udp->start(); \ No newline at end of file diff --git a/Server/ws.php b/Server/ws.php new file mode 100644 index 0000000..f6fe913 --- /dev/null +++ b/Server/ws.php @@ -0,0 +1,128 @@ +server = new Swoole\WebSocket\Server(self::HOST, self::PORT); + + // 设置响应html文件模式以及定义路径 + $this->server->set([ + 'worker_num' => 2, + 'task_worker_num' => 2, + 'enable_static_handler' => true, + 'document_root' => dirname(dirname(__FILE__)) . '/Template' + ]); + + // 监听客户端握手成功 + $this->server->on('Open', [$this, 'onOpen']); + // 监听客户端发送消息 + $this->server->on('Message', [$this, 'onMessage']); + // 监听task任务执行 + $this->server->on('Task', [$this, 'onTask']); + // 监听task任务完成 + $this->server->on('Finish', [$this, 'onFinish']); + // 监听关闭 + $this->server->on('Close', [$this, 'onClose']); + } + + /** + * 监听客户端握手成功 + * @param $ws Swoole\WebSocket\Server WebSocket对象 + * @param $request object 请求对象 + */ + public function onOpen($ws, $request) + { + echo 'A new websocket client is connected, this client id is ' . $request->fd . PHP_EOL; + // 每隔10秒执行定时器,向服务端输出信息 + Swoole\Timer::tick(10000, function ($timer_id) { + echo "waiting client send message. this timer id is " . $timer_id . PHP_EOL; + }); + } + + /** + * 监听客户端发送消息 + * @param $ws Swoole\WebSocket\Server WebSocket对象 + * @param $frame object 客户端数据对象 + */ + public function onMessage($ws, $frame) + { + echo "Receive from {$frame->fd} : {$frame->data}, opcode : {$frame->opcode}, fin : {$frame->finish}" . PHP_EOL; + $data = [ + 'name' => 'neo', + 'age' => 30 + ]; + // 投递task任务 + $ws->task($data); + + // 延时执行定时器,指定5秒后给客户端发送消息 + Swoole\Timer::after(5000, function () use ($ws, $frame) { + echo '5s-timer-after.' . PHP_EOL; + $ws->push($frame->fd, 'message_after-push, this time is ' . date('Y-m-d H:i:s')); + }); + + // 给客户端立即推送消息 + $ws->push($frame->fd, 'message-push-success, this time is ' . date('Y-m-d H:i:s')); + } + + /** + * 监听task任务执行 + * @param $serv Swoole\WebSocket\Server WebSocket对象 + * @param $task_id int task任务ID + * @param $worker_id int worker进程ID + * @param $data array 传递的数据 + * @return string 执行结果 + */ + public function onTask($serv, $task_id, $worker_id, $data) + { + // 打印传递过来的数据 + var_dump($data); + // 模拟耗时场景,执行10秒 + sleep(10); + // 告诉worker结果 + return 'on task finish.'; + } + + /** + * 监听task任务完成 + * @param $serv Swoole\WebSocket\Server WebSocket对象 + * @param $task_id int task任务ID + * @param $data string onTask执行完返回的结果 + */ + public function onFinish($serv, $task_id, $data) + { + echo "Finish task id: {$task_id}" . PHP_EOL; + echo "Finish data message: {$data}" . PHP_EOL; + } + + /** + * 监听关闭 + * @param $ws Swoole\WebSocket\Server WebSocket对象 + * @param $client_id int 客户端连接ID + */ + public function onClose($ws, $client_id) + { + echo "client-{$client_id} is closed" . PHP_EOL; + } + + /** + * 启动WebSocket服务器 + */ + public function start() + { + $this->server->start(); + } +} + +$webSocket = new Ws(); +$webSocket->start(); \ No newline at end of file diff --git a/Template/index.html b/Template/index.html new file mode 100644 index 0000000..7f2dc8e --- /dev/null +++ b/Template/index.html @@ -0,0 +1,11 @@ + + + + + 我的Swoole主页 + + +

欢迎来到我的Swoole主页

+

We just do it!

+ + \ No newline at end of file diff --git a/Template/ws.html b/Template/ws.html new file mode 100644 index 0000000..cb18263 --- /dev/null +++ b/Template/ws.html @@ -0,0 +1,35 @@ + + + + + 我的SwooleWebSocket主页 + + +

Hello Swoole WebSocket.

+
+ + + \ No newline at end of file