Skip to content

Commit 3dc927d

Browse files
committed
update
1 parent 13b11fe commit 3dc927d

31 files changed

+3152
-333
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
],
1515
"require": {
1616
"php": ">=7.0.0",
17+
"amphp/amp": "^2.0.1",
1718
"inhere/console": "dev-master",
1819
"inhere/library": "dev-master"
1920
},

examples/chatRoom/index.html

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Title</title>
6+
</head>
7+
<body>
8+
<input type="text" id="input" placeholder="Message…" />
9+
<hr />
10+
<pre id="output"></pre>
11+
12+
<script>
13+
var host = 'ws://127.0.0.1:8889';
14+
var socket = null;
15+
var input = document.getElementById('input');
16+
var output = document.getElementById('output');
17+
var print = function (message) {
18+
var samp = document.createElement('samp');
19+
samp.innerHTML = message + '\n';
20+
output.appendChild(samp);
21+
22+
return;
23+
};
24+
25+
input.addEventListener('keyup', function (evt) {
26+
if (13 === evt.keyCode) {
27+
var msg = input.value;
28+
29+
if (!msg) {
30+
return;
31+
}
32+
33+
try {
34+
socket.send(msg);
35+
input.value = '';
36+
input.focus();
37+
} catch (e) {
38+
console.log(e);
39+
}
40+
41+
return;
42+
}
43+
});
44+
45+
try {
46+
socket = new WebSocket(host);
47+
socket.onopen = function () {
48+
print('connection is opened');
49+
input.focus();
50+
51+
return;
52+
};
53+
socket.onmessage = function (msg) {
54+
print(msg.data);
55+
56+
return;
57+
};
58+
socket.onclose = function () {
59+
print('connection is closed');
60+
61+
return;
62+
};
63+
} catch (e) {
64+
console.log(e);
65+
}
66+
</script>
67+
</body>
68+
</html>

src/Application.php

Lines changed: 209 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use inhere\console\io\Input;
1212
use inhere\console\io\Output;
13+
use inhere\console\utils\Show;
1314
use inhere\library\helpers\PhpHelper;
1415
use inhere\library\helpers\ProcessHelper;
1516
use inhere\library\traits\EventTrait;
@@ -62,13 +63,16 @@ class Application
6263
use EventTrait;
6364

6465
// some events
65-
const ON_WS_CONNECT = 'wsConnect';
66-
const ON_WS_OPEN = 'wsOpen';
67-
const ON_WS_MESSAGE = 'wsMessage';
68-
const ON_WS_CLOSE = 'wsClose';
69-
const ON_WS_ERROR = 'wsError';
70-
const ON_NO_MODULE = 'noModule';
71-
const ON_PARSE_ERROR = 'parseError';
66+
const EVT_WS_CONNECT = 'wsConnect';
67+
const EVT_WS_OPEN = 'wsOpen';
68+
const EVT_WS_DISCONNECT = 'wsDisconnect';
69+
const EVT_HANDSHAKE_REQUEST = 'handshakeRequest';
70+
const EVT_HANDSHAKE_SUCCESSFUL = 'handshakeSuccessful';
71+
const EVT_WS_MESSAGE = 'wsMessage';
72+
const EVT_WS_CLOSE = 'wsClose';
73+
const EVT_WS_ERROR = 'wsError';
74+
const EVT_NO_MODULE = 'noModule';
75+
const EVT_PARSE_ERROR = 'parseError';
7276

7377
// custom ws handler position
7478
const OPEN_HANDLER = 0;
@@ -162,6 +166,10 @@ class Application
162166
*/
163167
private $modules;
164168

169+
private $pidFile;
170+
171+
private $bootstrapped = false;
172+
165173
/**
166174
* Application constructor.
167175
* @param string $host
@@ -258,7 +266,7 @@ protected function handleCliCommand()
258266
break;
259267
default:
260268
$this->cliOut->error("The command [{$command}] is don't supported!");
261-
$this->showHelpInfo();
269+
$this->help();
262270
break;
263271
}
264272

@@ -306,7 +314,7 @@ protected function checkInputCommand($command)
306314
}
307315
}
308316

309-
public function start($daemon = null)
317+
public function bootstrap()
310318
{
311319
// prepare server instance
312320
$this->prepareServer();
@@ -318,7 +326,7 @@ public function start($daemon = null)
318326
$this->ws->on(WSInterface::ON_CLOSE, [$this, 'handleClose']);
319327
$this->ws->on(WSInterface::ON_ERROR, [$this, 'handleError']);
320328

321-
// if not register route, add root path route handler
329+
// if not register route, add a default root path module handler
322330
if (0 === count($this->modules)) {
323331
$this->module('/', new RootModule);
324332
}
@@ -327,46 +335,188 @@ public function start($daemon = null)
327335
$this->ws->start();
328336
}
329337

330-
public function restart($daemon = null)
338+
/**
339+
* @param bool $value
340+
* @return $this
341+
*/
342+
public function asDaemon($value = true)
331343
{
332-
// prepare server instance
333-
$this->prepareServer();
344+
$this->daemon = (bool)$value;
345+
$this->config['swoole']['daemonize'] = (bool)$value;
346+
347+
return $this;
348+
}
349+
350+
/**
351+
* Do start server
352+
* @param null|bool $daemon
353+
*/
354+
public function start($daemon = null)
355+
{
356+
if ($pid = $this->getPidFromFile(true)) {
357+
Show::error("The swoole server({$this->name}) have been started. (PID:{$pid})", -1);
358+
}
334359

335-
if ($this->ws->isRunning()) {
336-
$this->stop();
360+
if (null !== $daemon) {
361+
$this->asDaemon($daemon);
337362
}
338363

339-
$this->start($daemon);
364+
if (!$this->bootstrapped) {
365+
$this->bootstrap();
366+
}
367+
368+
self::$_statistics['start_time'] = microtime(1);
369+
370+
$this->beforeServerStart();
371+
372+
$this->server->start();
373+
}
374+
375+
/**
376+
* before Server Start
377+
*/
378+
public function beforeServerStart()
379+
{
340380
}
341381

342-
public function reload($onlyTask = false)
382+
/**
383+
* do Reload Workers
384+
* @param boolean $onlyTaskWorker
385+
* @return int
386+
*/
387+
public function reload($onlyTaskWorker = false)
343388
{
389+
if (!$masterPid = $this->getPidFromFile(true)) {
390+
return Show::error("The swoole server({$this->name}) is not started.", true);
391+
}
392+
393+
// SIGUSR1: 向管理进程发送信号,将平稳地重启所有worker进程; 也可在PHP代码中调用`$server->reload()`完成此操作
394+
$sig = SIGUSR1;
395+
396+
// SIGUSR2: only reload task worker
397+
if ($onlyTaskWorker) {
398+
$sig = SIGUSR2;
399+
Show::notice('Will only reload task worker');
400+
}
344401

402+
if (!posix_kill($masterPid, $sig)) {
403+
Show::error("The swoole server({$this->name}) worker process reload fail!", -1);
404+
}
405+
406+
return Show::success("The swoole server({$this->name}) worker process reload success.", 0);
345407
}
346408

347-
public function stop()
409+
/**
410+
* Do restart server
411+
* @param null|bool $daemon
412+
*/
413+
public function restart($daemon = null)
348414
{
349-
if ($this->ws->isRunning()) {
350-
$this->cliOut->error('server is not running!');
415+
if ($this->getPidFromFile(true)) {
416+
$this->stop(false);
351417
}
352418

353-
ProcessHelper::kill($this->ws->getPid());
419+
$this->start($daemon);
420+
}
421+
422+
/**
423+
* Do stop swoole server
424+
* @param boolean $quit Quit, When stop success?
425+
* @return int
426+
*/
427+
public function stop($quit = true)
428+
{
429+
if (!$masterPid = $this->getPidFromFile(true)) {
430+
return Show::error("The swoole server({$this->name}) is not running.", true);
431+
}
432+
433+
Show::write("The swoole server({$this->name}:{$masterPid}) process stopping ", false);
434+
435+
// do stop
436+
// 向主进程发送此信号(SIGTERM)服务器将安全终止;也可在PHP代码中调用`$server->shutdown()` 完成此操作
437+
$masterPid && posix_kill($masterPid, SIGTERM);
438+
439+
$timeout = 10;
440+
$startTime = time();
441+
442+
// retry stop if not stopped.
443+
while (true) {
444+
Show::write('.', false);
445+
446+
if (!@posix_kill($masterPid, 0)) {
447+
break;
448+
}
449+
450+
// have been timeout
451+
if ((time() - $startTime) >= $timeout) {
452+
Show::error("The swoole server({$this->name}) process stop fail!", -1);
453+
}
454+
455+
usleep(300000);
456+
}
457+
458+
$this->removePidFile();
459+
460+
// stop success
461+
return Show::write(" <success>Stopped</success>\nThe swoole server({$this->name}) process stop success", $quit);
462+
}
463+
464+
public function help()
465+
{
466+
$this->showHelpInfo($this->cliIn->getScript());
467+
}
468+
469+
public function info()
470+
{
471+
$this->showInformation();
472+
}
473+
474+
public function status()
475+
{
476+
$this->showRuntimeStatus();
477+
}
478+
479+
/**
480+
* Show server info
481+
*/
482+
protected function showInformation()
483+
{
484+
// $swOpts = $this->config['swoole'];
485+
// $main = $this->config['main_server'];
486+
$panelData = [
487+
'System Info' => [
488+
'PHP Version' => PHP_VERSION,
489+
'Operate System' => PHP_OS,
490+
],
491+
];
492+
493+
494+
// 'Server Information'
495+
Show::mList($panelData);
496+
// Show::panel($panelData, 'Server Information');
497+
}
498+
499+
/**
500+
* show server runtime status information
501+
*/
502+
protected function showRuntimeStatus()
503+
{
504+
Show::notice('Sorry, The function un-completed!', 0);
354505
}
355506

356507
/**
357508
* Show help
509+
* @param $scriptName
358510
* @param boolean $showHelpAfterQuit
359511
*/
360-
public function showHelpInfo($showHelpAfterQuit = true)
512+
public function showHelpInfo($scriptName, $showHelpAfterQuit = true)
361513
{
362-
$scriptName = $this->cliIn->getScriptName();
363-
364514
// 'bin/test_server.php'
365515
if (strpos($scriptName, '.') && 'php' === pathinfo($scriptName, PATHINFO_EXTENSION)) {
366516
$scriptName = 'php ' . $scriptName;
367517
}
368518

369-
$this->cliOut->helpPanel([
519+
Show::helpPanel([
370520
'description' => 'webSocket server tool, Version <comment>' . ServerAbstracter::VERSION .
371521
'</comment> Update time ' . ServerAbstracter::UPDATE_TIME,
372522
'usage' => "$scriptName {start|reload|restart|stop|status} [-d]",
@@ -393,6 +543,40 @@ public function showHelpInfo($showHelpAfterQuit = true)
393543
], $showHelpAfterQuit);
394544
}
395545

546+
/**
547+
* @param bool $checkRunning
548+
* @return int
549+
*/
550+
public function getPidFromFile($checkRunning = false)
551+
{
552+
return ProcessHelper::getPidFromFile($this->pidFile, $checkRunning);
553+
}
554+
555+
/**
556+
* @param (int) $masterPid
557+
* @return bool|int
558+
*/
559+
protected function createPidFile($masterPid)
560+
{
561+
if ($this->pidFile) {
562+
return file_put_contents($this->pidFile, $masterPid);
563+
}
564+
565+
return false;
566+
}
567+
568+
/**
569+
* @return bool
570+
*/
571+
protected function removePidFile()
572+
{
573+
if ($this->pidFile && file_exists($this->pidFile)) {
574+
return unlink($this->pidFile);
575+
}
576+
577+
return false;
578+
}
579+
396580
/**
397581
* webSocket 只会在连接握手时会有 request, response
398582
* @param Request $request

0 commit comments

Comments
 (0)