Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6367b4a

Browse files
author
jianyan74
committed
实例上传
1 parent 2ff759a commit 6367b4a

File tree

3 files changed

+378
-2
lines changed

3 files changed

+378
-2
lines changed

‎README.md‎

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,48 @@
1-
## Yii2 WebScoket
1+
## Yii2 WebSocket
22

3-
即时通讯,直播间demo
3+
即时通讯,直播间demo
4+
5+
### 前提安装swoole
6+
7+
```
8+
git clone https://github.com/swoole/swoole-src.git
9+
cd swoole-src
10+
phpize
11+
./configure --enable-openssl -with-php-config=[PATH] #注意[PATH]为你的php地址 开启ssl用
12+
make && make install
13+
```
14+
### 安装
15+
16+
```
17+
composer require "jianyan74/yii2-websocket"
18+
```
19+
### 配置
20+
21+
`console/config/main.php` 加入以下配置。(注意:配置在controllerMap里面)
22+
23+
```
24+
'web-socket' => [
25+
'class' => 'jianyan\websocket\WebSocketController',
26+
'host' => '0.0.0.0',// 监听地址
27+
'port' => 9501,// 监听端口
28+
'config' => [// 标准的swoole配置项都可以再此加入
29+
'daemonize' => false,// 守护进程执行
30+
'ssl_cert_file' => '',
31+
'ssl_key_file' => '',
32+
'pid_file' => __DIR__ . '/../../backend/runtime/logs/server.pid',
33+
'log_file' => __DIR__ . '/../../backend/runtime/logs/swoole.log',
34+
'log_level' => 0,
35+
],
36+
],
37+
```
38+
39+
### 使用
40+
41+
```
42+
# 启动
43+
php ./yii web-socket/start
44+
# 停止
45+
php ./yii web-socket/stop
46+
# 重启
47+
php ./yii web-socket/restart
48+
```

‎src/WebSocketController.php‎

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
namespace jianyan74\websocket;
3+
4+
use Yii;
5+
use yii\console\Controller;
6+
use yii\helpers\FileHelper;
7+
use common\components\WebSocket;
8+
9+
/**
10+
* WebSocket
11+
* 启动 php ./yii web-socket/start
12+
* 停止 php ./yii web-socket/stop
13+
* 重启 php ./yii web-socket/restart
14+
*
15+
* Class WebSocketController
16+
* @package console\controllers
17+
*/
18+
class WebSocketController extends Controller
19+
{
20+
/**
21+
* 监听地址
22+
*
23+
* @var string
24+
*/
25+
public $host = '0.0.0.0';
26+
27+
/**
28+
* 监听端口
29+
*
30+
* @var string
31+
*/
32+
public $port = 9501;
33+
34+
/**
35+
* 运行的模式
36+
*
37+
* @var
38+
* SWOOLE_PROCESS 多进程模式(默认)
39+
* SWOOLE_BASE 基本模式
40+
*/
41+
public $mode = SWOOLE_BASE;
42+
43+
/**
44+
* @var
45+
* SWOOLE_SOCK_TCP
46+
*/
47+
public $socketType = SWOOLE_SOCK_TCP;
48+
49+
/**
50+
* swoole 配置
51+
*
52+
* @var array
53+
*/
54+
public $config = [
55+
'daemonize' => false, // 守护进程执行
56+
'ssl_cert_file' => '',
57+
'ssl_key_file' => '',
58+
'pid_file' => '',
59+
];
60+
61+
/**
62+
* 启动
63+
*
64+
* @throws \yii\base\Exception
65+
*/
66+
public function actionStart()
67+
{
68+
if ($this->getPid() !== false)
69+
{
70+
$this->stderr("服务已经启动");
71+
exit(1);
72+
}
73+
74+
// 写入进程
75+
$this->setPid();
76+
77+
// 运行
78+
$ws = new WebSocket($this->host, $this->port, $this->mode, $this->socketType, $this->config);
79+
$ws->run();
80+
81+
$this->stdout("服务正在运行,监听 {$this->host}:{$this->port}" . PHP_EOL);
82+
}
83+
84+
/**
85+
* 关闭进程
86+
*/
87+
public function actionStop()
88+
{
89+
$this->sendSignal(SIGTERM);
90+
$this->stdout("服务已经停止, 停止监听 {$this->host}:{$this->port}" . PHP_EOL);
91+
}
92+
93+
/**
94+
* 重启进程
95+
*
96+
* @throws \yii\base\Exception
97+
*/
98+
public function actionRestart()
99+
{
100+
$this->sendSignal(SIGTERM);
101+
$time = 0;
102+
while (posix_getpgid($this->getPid()) && $time <= 10)
103+
{
104+
usleep(100000);
105+
$time++;
106+
}
107+
108+
if ($time > 100)
109+
{
110+
$this->stderr("服务停止超时" . PHP_EOL);
111+
exit(1);
112+
}
113+
114+
if( $this->getPid() === false )
115+
{
116+
$this->stdout("服务重启成功" . PHP_EOL);
117+
}
118+
else
119+
{
120+
$this->stderr("服务停止错误, 请手动处理杀死进程" . PHP_EOL);
121+
}
122+
123+
$this->actionStart();
124+
}
125+
126+
/**
127+
* 发送信号
128+
*
129+
* @param $sig
130+
*/
131+
private function sendSignal($sig)
132+
{
133+
if ($pid = $this->getPid())
134+
{
135+
posix_kill($pid, $sig);
136+
}
137+
else
138+
{
139+
$this->stdout("服务未运行!" . PHP_EOL);
140+
exit(1);
141+
}
142+
}
143+
144+
/**
145+
* 获取pid进程
146+
*
147+
* @return bool|string
148+
*/
149+
private function getPid()
150+
{
151+
$pid_file = $this->config['pid_file'];
152+
if (file_exists($pid_file))
153+
{
154+
$pid = file_get_contents($pid_file);
155+
if (posix_getpgid($pid))
156+
{
157+
return $pid;
158+
}
159+
else
160+
{
161+
unlink($pid_file);
162+
}
163+
}
164+
165+
return false;
166+
}
167+
168+
/**
169+
* 写入pid进程
170+
*
171+
* @throws \yii\base\Exception
172+
*/
173+
private function setPid()
174+
{
175+
$parentPid = getmypid();
176+
$pidDir = dirname($this->config['pid_file']);
177+
if(!file_exists($pidDir)) FileHelper::createDirectory($pidDir);
178+
file_put_contents($this->config['pid_file'], $parentPid + 1);
179+
}
180+
}

‎src/WebSocketServer.php‎

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
namespace jianyan74\websocket;
3+
4+
use Yii;
5+
use swoole_table;
6+
use swoole_websocket_server;
7+
8+
/**
9+
* 长连接
10+
*
11+
* Class WebSocketServer
12+
* @package console\controllers
13+
*/
14+
class WebSocketServer
15+
{
16+
protected $_host;
17+
18+
protected $_port;
19+
20+
protected $_mode;
21+
22+
protected $_socketType;
23+
24+
protected $_config;
25+
26+
/**
27+
* 服务
28+
*
29+
* @var
30+
*/
31+
protected $_server;
32+
33+
/**
34+
* 基于共享内存和锁实现的超高性能,并发数据结构
35+
*
36+
* @var
37+
*/
38+
protected $_table;
39+
40+
/**
41+
* WebSocket constructor.
42+
* @param $host
43+
* @param $port
44+
* @param $config
45+
*/
46+
public function __construct($host, $port, $mode, $socketType, $config)
47+
{
48+
$this->_host = $host;
49+
$this->_port = $port;
50+
$this->_mode = $mode;
51+
$this->_socketType = $socketType;
52+
53+
$this->_config = $config;
54+
55+
// 创建内存表
56+
$this->createTable();
57+
}
58+
59+
public function run()
60+
{
61+
// 启动进程
62+
$this->_server = new swoole_websocket_server($this->_host, $this->_port, $this->_mode, $this->_socketType | SWOOLE_SSL);
63+
$this->_server->set([
64+
// 以非守护进程执行
65+
'daemonize' => $this->_config['daemonize'],
66+
// 配置wss
67+
'ssl_cert_file' => $this->_config['ssl_cert_file'],
68+
'ssl_key_file' => $this->_config['ssl_key_file'],
69+
]);
70+
71+
$this->_server->on('open', [$this, 'onOpen']);
72+
$this->_server->on('message', [$this, 'onMessage']);
73+
$this->_server->on('close', [$this, 'onClose']);
74+
$this->_server->start();
75+
}
76+
77+
/**
78+
* 开启连接
79+
*
80+
* @param $server
81+
* @param $frame
82+
*/
83+
public function onOpen($server, $frame)
84+
{
85+
echo "server: handshake success with fd{$frame->fd}\n";
86+
echo "server: {$frame->data}\n";
87+
88+
$this->_table->set($frame->fd, ['fd'=>$frame->fd]);
89+
}
90+
91+
/**
92+
* 消息
93+
*
94+
* @param $server
95+
* @param $frame
96+
*/
97+
public function onMessage($server, $frame)
98+
{
99+
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
100+
// 消息发送给自己
101+
$server->push($frame->fd, $frame->data);
102+
// 消息发送给别人
103+
$this->broadcast($frame->fd, $frame->data);
104+
}
105+
106+
/**
107+
* 关闭连接
108+
*
109+
* @param $ser
110+
* @param $fd
111+
*/
112+
public function onClose($ser, $fd)
113+
{
114+
echo "client {$fd} closed\n";
115+
// 删除
116+
$this->_table->del($fd);
117+
}
118+
119+
/**
120+
* 广播进程
121+
*
122+
* @param integer $client_id 客户端id
123+
* @param string $msg 广播消息
124+
*/
125+
public function broadcast($client_id, $msg)
126+
{
127+
//广播
128+
foreach ($this->_table as $cid => $info)
129+
{
130+
if ($client_id != $cid)
131+
{
132+
$this->_server->push($cid, $msg);
133+
}
134+
}
135+
}
136+
137+
/**
138+
* 创建内存表
139+
*
140+
* 数指定表格的最大行数,如果$size不是为2的N次方,如1024、8192,65536等,底层会自动调整为接近的一个数字
141+
* 占用的内存总数为 (结构体长度 + KEY长度64字节 + 行尺寸$size) * (1.2预留20%作为hash冲突) * (列尺寸),如果机器内存不足table会创建失败
142+
*/
143+
private function createTable()
144+
{
145+
$this->_table = new swoole_table(1024);
146+
$this->_table->column('fd', swoole_table::TYPE_INT);
147+
//$this->_table->column('name', swoole_table::TYPE_STRING, 255);
148+
//$this->_table->column('avatar', swoole_table::TYPE_STRING, 255);
149+
$this->_table->create();
150+
}
151+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /