先来看看服务器的代码,这次先封装一下
namespace Zhcsam\Io\Nonblocking;
class Worker
{
// 自定义服务的事件注册函数,
// 这三个是闭包函数
public $onReceive = null;
public $onConnect = null;
public $onClose = null;
// 连接
public $socket = null;
public function __construct($socket_address)
{
$this->socket = stream_socket_server($socket_address);
// echo $socket_address."\n";
// $this->debug('stream_socket_server($socket_address);');
// $this->debug($this->socket, true);
}
// 需要处理事情
public function accept()
{
// 接收连接和处理使用
while (true) {
$this->debug("accept start");
// 监听的过程是阻塞的
$client = stream_socket_accept($this->socket);
// is_callable判断一个参数是不是闭包
if (is_callable($this->onConnect)) {
// 执行函数
($this->onConnect)($this, $client);
}
// tcp 处理 大数据 重复多发几次
// $buffer = "";
// while (!feof($client)) {
// $buffer = $buffer.fread($client, 65535);
// }
$data = fread($client, 65535);
if (is_callable($this->onReceive)) {
($this->onReceive)($this, $client, $data);
}
$this->debug("accept end");
// 处理完成之后关闭连接
// 心跳检测 - 自己的心跳
// fclose($client);
}
}
public function debug($data, $flag = false)
{
if ($flag) {
var_dump($data);
} else {
echo "==== >>>> : ".$data." \n";
}
}
// 发送信息
public function send($client, $data)
{
$response = "HTTP/1.1 200 OK\r\n";
$response .= "Content-Type: text/html;charset=UTF-8\r\n";
$response .= "Connection: keep-alive\r\n";
$response .= "Content-length: ".strlen($data)."\r\n\r\n";
$response .= $data;
echo '发送信息中。。。。';
fwrite($client, $response);
}
// 启动服务的
public function start()
{
$this->accept();
}
}
再来生成服务器实例,代码如下
此函数的闭包函数赋值给主类的成员
<?php
require __DIR__.'/../../vendor/autoload.php’;
use Zhcsam\Io\NonBlocking\Worker;
$host = "tcp://0.0.0.0:9000";
$server = new Worker($host);
$server->onConnect = function($socket, $client){
echo "有一个连接进来了\n";
};
// 接收和处理信息
$server->onReceive = function($socket, $client, $data){
echo "给连接发送信息2222\n";
sleep(3);
$socket->send($client, "hello world cli8888ent \n");
// fwrite($client, "server hellow");
};
$server->start();
然后再来看看客户端的代码
<?php
$host ="tcp://0.0.0.0:9000";
$cliect = stream_socket_client($host);
stream_set_blocking($cliect, 0);
$new =time();
echo "客户端连接中\n";
fwrite($cliect,'客户端发来信息');
echo "其它业务\n";
echo "用时".(time()-$new)."\n";
while (!feof($cliect)) {
echo "轮询中……\n";
var_dump(fread($cliect, 65535));
sleep(1);
}
客户端用stream_set_blocking设置非阻塞,服务端也是可以设置
在命令行运行服务端
php server.php
==== >>>> : accept start
(此时正在等待客户端连接)
命令行运行客户端
php client.php
客户端连接中
其它业务
用时0
轮询中……
string(0) ""
轮询中……
string(0) ""
轮询中……
string(0) ""
轮询中……
string(126) "HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Connection: keep-alive
Content-length: 24
hello world cli8888ent
"
string(0) ""
轮询中……
string(0) ""
轮询中……
string(0) ""
一直重复执行
服务端的界面如下:
==== >>>> : accept start
有一个连接进来了
给连接发送信息2222
发送信息中。。。。==== >>>> : accept end
==== >>>> : accept start
(服务器重新监听是否有下一次新的连接)
从客户端的界面可以观察到:
- 用时为0,但数据并没有马上返回
- 需要轮询,几秒后服务器才返回,打印出带“hello world cli8888ent ”等文字
非阻塞的模式后面也是不断要轮询,较消耗资源