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