PHP Swoole-Demo TCP服务端简单实现
发布时间:2020-05-25 08:16:58 所属栏目:PHP 来源:互联网
导读:tcp 服务端简单demo与client . 1 lt;?php 2 /** 3 * author : rookiejin lt;mrjnamei@gmail.comgt; 4 * create
|
1 <?php
2 /**
3 * author : rookiejin <mrjnamei@gmail.com>
4 * createTime : 2018/1/4 10:26
5 * description: tcp.php - swoole-demo
6 * 该代码是一份简单的面向对象形式的 tcp 服务器和客户端通讯的demo
7 * 功能:实现服务器端tcp简单demo
8 */
9 // 创建一个tcp服务器
10
11 $server = new swoole_server("127.0.0.1",9501);
12
13 /**
14 * @var $server swoole_server
15 * @var $fd int 文件描述符
16 */
17 $server->on("connect",function($server,$fd){
18 echo "a client connectedn" ;
19 });
20
21 /**
22 * @var $server swoole_server
23 * @var $fd int 文件描述符
24 * @var $from_id worker_id worker进程id
25 * @var $data 接受的数据
26 */
27 $server->on("receive",$fd,$from_id,$data){
28 echo "#server received msg:",$data,"n";
29 $server->send($fd,"i received");
30 });
31
32 /**
33 * @var $server swoole_server
34 * @var $fd 文件描述符
35 */
36 $server->on("close",$fd){
37 echo "# client closedn";
38 });
39 // 启动服务器
40 $server->start();
41 client.php
42
43 <?php
44
45 $client = new swoole_client(SWOOLE_SOCK_TCP);
46
47 if(!$client->connect("127.0.0.1",9501,-1)){
48 exit("connect failed" . $client->errCode . "n");
49 }
50
51 $client->send("helloworld");
52 echo $client->recv(),"n";
53 $client->close();
2. 使用面向对象的方式来写TCP服务器. 1 <?php
2 /**
3 * author : rookiejin <mrjnamei@gmail.com>
4 * createTime : 2018/1/4 10:26
5 * description: php_oop.php - swoole-demo
6 * 该代码是一份干净的tcp server 事件回调,
7 * 没有任何对事件回调的业务处理 .
8 * 以该代码为基准,后面的demo都在此基础上修改 .
9 */
10
11 class Server {
12
13 /**
14 * @var swoole_server
15 */
16 public $server ;
17
18 /**
19 * 配置项
20 * @var $config array
21 */
22 public $config ;
23
24 /**
25 * @var Server
26 */
27 public static $_worker ;
28
29 /**
30 * 存储pid文件的位置
31 */
32 public $pidFile ;
33
34 /**
35 * worker 进程的数量
36 * @var $worker_num
37 */
38 public $worker_num;
39
40 /**
41 * 当前进程的worker_id
42 * @var $worker_id
43 */
44 public $worker_id ;
45
46 /**
47 * task 进程数 + worker 进程数 = 总的服务进程
48 * 给其他的进程发送消息:
49 * for($i = 0 ; $i < $count ; $i ++) {
50 * if($i == $this->worker_id) continue;表示是该进程
51 * $this->server->sendMessage($i,$data);
52 * }
53 * task 进程的数量
54 * @var $task_num
55 */
56 public $task_num ;
57
58 /**
59 * Server constructor.
60 *
61 * @param array $config
62 */
63 public function __construct(array $config)
64 {
65 $this->server = new swoole_server($config ['host'],$config ['port']);
66 $this->config = $config;
67 $this->serverConfig();
68 self::$_worker = & $this; // 引用
69 }
70
71 public function serverConfig()
72 {
73 $this->server->set($this->config['server']);
74 }
75
76 public function start()
77 {
78 // Server启动在主进程的主线程回调此函数
79 $this->server->on("start",[$this,"onSwooleStart"]);
80 // 此事件在Server正常结束时发生
81 $this->server->on("shutDown","onSwooleShutDown"]);
82 //事件在Worker进程/Task进程启动时发生。这里创建的对象可以在进程生命周期内使用。
83 $this->server->on("workerStart","onSwooleWorkerStart"]);
84 // 此事件在worker进程终止时发生。在此函数中可以回收worker进程申请的各类资源。
85 $this->server->on("workerStop","onSwooleWorkerStop"]);
86 // worker 向task_worker进程投递任务触发
87 $this->server->on("task","onSwooleTask"]);
88 // task_worker 返回值传给worker进程时触发
89 $this->server->on("finish","onSwooleFinish"]);
90 // 当工作进程收到由 sendMessage 发送的管道消息时会触发onPipeMessage事件
91 $this->server->on("pipeMessage","onSwoolePipeMessage"]);
92 // 当worker/task_worker进程发生异常后会在Manager进程内回调此函数
93 $this->server->on("workerError","onSwooleWrokerError"]);
94 // 当管理进程启动时调用它,函数原型:
95 $this->server->on("managerStart","onSwooleManagerStart"]);
96 // onManagerStop
97 $this->server->on("managerStop","onSwooleManagerStop"]);
98 // 有新的连接进入时,在worker进程中回调。
99 $this->server->on("connect",'onSwooleConnect']);
100 // 接收到数据时回调此函数,发生在worker进程中
101 $this->server->on("receive",'onSwooleReceive']);
102 //CP客户端连接关闭后,在worker进程中回调此函数。函数原型:
103 $this->server->on("close","onSwooleClose"]);
104 $this->server->start();
105 }
106
107 /**
108 * @warning 进程隔离
109 * 该步骤一般用于存储进程的 master_pid 和 manager_pid 到文件中
110 * 本例子存储的位置是 __DIR__ . "/tmp/" 下面
111 * 可以用 kill -15 master_pid 发送信号给进程关闭服务器,并且触发下面的onSwooleShutDown事件
112 * @param $server
113 */
114 public function onSwooleStart($server)
115 {
116 $this->setProcessName('SwooleMaster');
117 $debug = debug_backtrace();
118 $this->pidFile = __DIR__ . "/temp/" . str_replace("/","_",$debug[count($debug) - 1] ["file"] . ".pid" );
119 $pid = [$server->master_pid,$server->manager_pid];
120 file_put_contents($this->pidFile,implode(",",$pid));
121 }
122
123 /**
124 * @param $server
125 * 已关闭所有Reactor线程、HeartbeatCheck线程、UdpRecv线程
126 * 已关闭所有Worker进程、Task进程、User进程
127 * 已close所有TCP/UDP/UnixSocket监听端口
128 * 已关闭主Reactor
129 * @warning
130 * 强制kill进程不会回调onShutdown,如kill -9
131 * 需要使用kill -15来发送SIGTREM信号到主进程才能按照正常的流程终止
132 * 在命令行中使用Ctrl+C中断程序会立即停止,底层不会回调onShutdown
133 */
134 public function onSwooleShutDown($server)
135 {
136 echo "shutdownn";
137 }
138
139 /**
140 * @warning 进程隔离
141 * 该函数具有进程隔离性,142 * {$this} 对象从 swoole_server->start() 开始前设置的属性全部继承
143 * {$this} 对象在 onSwooleStart,onSwooleManagerStart中设置的对象属于不同的进程中.
144 * 因此这里的pidFile虽然在onSwooleStart中设置了,但是是不同的进程,所以找不到该值.
145 * @param swoole_server $server
146 * @param int $worker_id
147 */
148 public function onSwooleWorkerStart(swoole_server $server,int $worker_id)
149 {
150 if($this->isTaskProcess($server))
151 {
152 $this->setProcessName('SwooleTask');
153 }
154 else{
155 $this->setProcessName('SwooleWorker');
156 }
157 $debug = debug_backtrace();
158 $this->pidFile = __DIR__ . "/temp/" . str_replace("/",$debug[count($debug) - 1] ["file"] . ".pid" );
159 file_put_contents($this->pidFile,{$worker_id}", FILE_APPEND);
160 }
161
162 public function onSwooleWorkerStop($server,$worker_id)
163 {
164 echo "#worker exited {$worker_id}n";
165 }
166
167 /**
168 * @warning 进程隔离 在task_worker进程内被调用
169 * worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务
170 * $task_id和$src_worker_id组合起来才是全局唯一的,不同的worker进程投递的任务ID可能会有相同
171 * 函数执行时遇到致命错误退出,或者被外部进程强制kill,当前的任务会被丢弃,但不会影响其他正在排队的Task
172 * @param $server
173 * @param $task_id 是任务ID 由swoole扩展内自动生成,用于区分不同的任务
174 * @param $src_worker_id 来自于哪个worker进程
175 * @param $data 是任务的内容
176 * @return mixed $data
177 */
178 public function onSwooleTask($server,$task_id,$src_worker_id,$data)
179 {
180 return $data ;
181 }
182
183 public function onSwooleFinish()
184 {
185
186 }
187
188 /**
189 * 当工作进程收到由 sendMessage 发送的管道消息时会触发onPipeMessage事件。worker/task进程都可能会触发onPipeMessage事件。
190 * @param $server
191 * @param $src_worker_id 消息来自哪个Worker进程
192 * @param $message 消息内容,可以是任意PHP类型
193 */
194 public function onSwoolePipeMessage($server,$message)
195 {
196
197 }
198
199 /**
200 * worker进程发送错误的错误处理回调 .
201 * 记录日志等操作
202 * 此函数主要用于报警和监控,一旦发现Worker进程异常退出,那么很有可能是遇到了致命错误或者进程CoreDump。通过记录日志或者发送报警的信息来提示开发者进行相应的处理。
203 * @param $server
204 * @param $worker_id 是异常进程的编号
205 * @param $worker_pid 是异常进程的ID
206 * @param $exit_code 退出的状态码,范围是 1 ~255
207 * @param $signal 进程退出的信号
208 */
209 public function onSwooleWrokerError($server,$worker_id,$worker_pid,$exit_code,$signal)
210 {
211 echo "#workerError:{$worker_id}n";
212 }
213
214 /**
215 *
216 */
217 public function onSwooleManagerStart()
218 {
219 $this->setProcessName('SwooleManager');
220 }
221
222 /**
223 * @param $server
224 */
225 public function onSwooleManagerStop($server)
226 {
227 echo "#managerstopn";
228 }
229
230 /**
231 * 客户端连接
232 * onConnect/onClose这2个回调发生在worker进程内,而不是主进程。
233 * UDP协议下只有onReceive事件,没有onConnect/onClose事件
234 * @param $server
235 * @param $fd
236 * @param $reactorId
237 */
238 public function onSwooleConnect($server,$reactorId)
239 {
240 echo "#connectedn";
241 }
242
243 /**
244 * @param $server server对象
245 * @param $fd 文件描述符
246 * @param $reactorId reactor线程id
247 */
248 public function onSwooleReceive($server,$reactorId)
249 {
250 echo "#receivedn";
251 }
252
253 /**
254 * 连接断开,广播业务需要从redis | memcached | 内存 中删除该fd
255 * @param $server
256 * @param $fd
257 * @param $reactorId
258 */
259 public function onSwooleClose($server,$reactorId)
260 {
261 echo "#swooleClosedn" ;
262 }
263
264 public function setProcessName($name)
265 {
266 if(function_exists('cli_set_process_title'))
267 {
268 @cli_set_process_title($name);
269 }
270 else{
271 @swoole_set_process_name($name);
272 }
273 }
274
275 /**
276 * 返回真说明该进程是task进程
277 * @param $server
278 * @return bool
279 */
280 public function isTaskProcess($server)
281 {
282 return $server->taskworker === true ;
283 }
284
285 /**
286 * main 运行入口方法
287 */
288 public static function main()
289 {
290 self::$_worker->start();
291 }
292 }
293
294 $config = ['server' => ['worker_num' => 4,"task_worker_num" => "20","dispatch_mode" => 3 ],'host' => '0.0.0.0','port' => 9501];
295 $server = new Server($config);
296 Server::main() ;
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
