内容简介:有研究过Workman框架的同学就会发现,其实workman最核心的,就是用了php socket拓展加上pcntl拓展来实现其底层的网络服务和多进程调度。那我们今天就来探讨如何使用Swoole的CoroutineSocket模块来实现自己的tcp服务。我们先编写一段小的测试代码,test.php 代码如下我们执行
有研究过Workman框架的同学就会发现,其实workman最核心的,就是用了php socket拓展加上pcntl拓展来实现其底层的网络服务和多进程调度。那我们今天就来探讨如何使用Swoole的CoroutineSocket模块来实现自己的tcp服务。
我们先编写一段小的测试代码,test.php 代码如下
$socket = new Co\Socket(AF_INET, SOCK_STREAM, 0); $socket->bind('127.0.0.1', 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); $data = $client->recv(64,10); var_dump('Recv:'.$data); $client->sendAll('reply at '.time()); $client->close(); } });
我们执行
php test.php
并新建一个cmd控制台,用telnet模拟tcp客户端,可以看到如下结果:
telnet 127.0.0.1 9601 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. asd reply at 1559713416 Connection closed by foreign host
以上说明我们已经成功建立了一个简单的TCP服务器。而有细心的同学就会发现,以上代码如果我在recv后,有一些数据库行为发生,那我该TCP服务器在同一时间就仅仅只能accept链接并处理一个链接的事情,并发能力接近于1。因此我们可以做一点小小的改进,如下:
$socket = new Co\Socket(AF_INET, SOCK_STREAM, 0); $socket->bind('127.0.0.1', 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); go(function () use ($client){ $data = $client->recv(64,10); var_dump('Recv:'.$data); //模拟数据库耗时,假定我们的数据库也是用协程api \co::sleep(1); $client->sendAll('reply at '.time()); $client->close(); }); } });
我们利用协程,把连接accept后的逻辑,全部放到另外一个子协程当中处理,让我们的TCP服务器可以继续accept连接,也就提高了我们的并发能力。然而,在实际的编程中,我们不可能做到完全的百分百协程API,而且我的机器也是多核心的处理器,那么此刻我如何尽可能的利用我的CPU呢?因此我们可以利用端口复用的特性和Swoole的Process来构建一个多进程TCP协程服务器。
引入Process
因为在本章节中,对Swoole Process的封装不是我们关心的,因此我们这里直接使用EasySwoole封装好的进程组件。
composer require easyswoole/component
实现我的Process Class,代码如下
use Co\Socket; use EasySwoole\Component\Process\AbstractProcess; class Server extends AbstractProcess { protected function run($arg) { $socket = new Socket(AF_INET, SOCK_STREAM, 0); //关键在这里,允许复用 $socket->setOption(SOL_SOCKET,SO_REUSEPORT,true); $socket->setOption(SOL_SOCKET,SO_REUSEADDR,true); $socket->bind('127.0.0.1', 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); go(function () use ($client){ $data = $client->recv(64,10); var_dump('Recv:'.$data); //模拟数据库耗时,假定我们的数据库也是用协程api \co::sleep(1); $client->sendAll('reply at '.time()); $client->close(); }); } }); } }
我们在以上代码中,加入了允许端口复用的选项,否则在多进程模式下,会导致监听失败。我们在cli模式下,测试起五个进程
for ($i = 1;$i < 5;$i++){ $p = new Server("TcpServer.{$i}"); $p->getProcess()->start(); } //主进程要等待回收 while($ret = \Swoole\Process::wait()) { echo "PID={$ret['pid']}\n"; }
我们,这样就很简单的实现了一个多进程的TCP协程服务。总而言之,Swoole 4.x的协程能力,还是很强大的,让PHPer可以以最小的代价来实现一个高性能的TCP服务,而不是需要去学习新的一门语言,若需要更多的完善代码,可以参考 http://easyswoole.com/ 这个框架的项目代码,如果有喜欢的同学,可以随意点个 star ,github地址 https://github.com/easy-swool...
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构与算法分析
韦斯 (Mark Allen Weiss) / 陈越 / 机械工业出版社 / 2016-3-1 / 69.00元
本书是国外数据结构与算法分析方面的经典教材,使用卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计)。本书把算法分析与有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面、缜密严格,并细致讲解精心构造程序的方法。一起来看看 《数据结构与算法分析》 这本书的介绍吧!