workerman是一个高性能的PHP socket 服务器框架,workerman基于PHP多进程以及libevent事件轮询库,PHP开发者只要实现一两个接口,便可以开发出自己的网络应用,例如Rpc服务、聊天室服务器、手机游戏服务器等。
workerman的目标是让PHP开发者更容易的开发出基于socket的高性能的应用服务,而不用去了解PHP socket以及PHP多进程细节。 workerman本身是一个PHP多进程服务器框架,具有PHP进程管理以及socket通信的模块,所以不依赖php-fpm、nginx或者apache等这些容器便可以独立运行。
<?php
#服务端(server.php)
require_once __DIR__ . '/../../vendor/autoload.php';
require __DIR__.'/base.php';//自己的业务逻辑
use Workerman\Worker;
use Workerman\Lib\Timer;
use wegame\test;
// 心跳间隔30秒
define('HEARTBEAT_TIME', 30);
$worker = new Worker('websocket://0.0.0.0:1234');//监听地址和端口,支持http、tcp、text、ws和自定义协议
$worker->onMessage = function($connection, $data) {
// 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间
$connection->lastMessageTime = time();
// 其它业务逻辑...
$connection->send('hello your params:'.$data);//返回内容
// $connection->send((new test())->run($data));//自己的业务逻辑
};
// 4 processes
$worker->count = 1;
// Emitted when new connection come
$worker->onConnect = function ($connection) {
echo "New connection\n";
};
// Emitted when connection closed
$worker->onClose = function ($connection) {
//DebugServer::debug_log('test','close');
echo "Connection closed\n";
};
// 进程启动后设置一个每10秒运行一次的定时器
$worker->onWorkerStart = function($worker) {
Timer::add(10, function()use($worker){
$time_now = time();
foreach($worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
};
Worker::runAll();
#在命令行执行启动 php server.php start -d启动后在客户端进行测试(html即可):
<!DOCTYPE HTML>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>test</title>
<script type="text/javascript">
function WebSocketTest() {
if ("WebSocket" in window) {
alert("您的浏览器支持 WebSocket!");
// 打开一个 web socket
var ws = new WebSocket("ws://服务器IP:端口");
ws.onopen = function () {
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("发送的数据");
alert("数据发送中...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("数据已接收...");
};
ws.onclose = function () {
// 关闭 websocket
alert("连接已关闭...");
};
} else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">运行 WebSocket</a>
</div>
</body>
</html>查看上面的html调试结果发现成功了。
不成功排查:
服务端没有启动
服务器端口没有开放或防火墙没有设置开放
客户端和服务端用的协议不一致
服务端代码出错
注意事项:
每次修改逻辑代码后都需要重新执行启动(重启)服务端才有效,因为这个常驻内存的高效应用(用SVN开发的话可以在提交SVN后回调加入重启命令比较方便)。
长链接一定要设置心跳模式,否则容易被系统终止进程
常用命令:
php server.php connectionsphp server.php stopphp server.php restartphp server.php reload
其他参考:https://github.com/walkor/workerman