利用Swoole实现服务器通过WebSocket主动向浏览器推送数据

WebSocket 协议是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,允许服务器主动发送信息给客户端。

下面的代码演示了利用 Swoole 实现服务器向浏览器主动推送数据的例子。

Server端代码:

<?php
$server = new Swoole\Websocket\Server('192.168.1.1', 9501);

$server->on('Open', function($server, $req) {
    echo 'connection open: '.$req->fd . "\n";
    $server->push($req->fd, "welcome to www.sunbloger.com");
    for ($i=1; $i<=9; $i++) {
        $server->push($req->fd, $i);
        sleep(3);
    }
});

$server->on('Message', function($server, $req) {
    echo "client(".$req->fd."): " . $req->data . "\n";
});

$server->on('Close', function($server, $fd) {
    echo "connection close: {$fd}\n";
});

$server->on('WorkerStart', function ($server, $workerId) {
    echo "worker started: {$workerId}\n";
});

$server->start();
?>

 

浏览器端(Client)代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>WebSocket Client</title>
</head>
<body>  
  <input type="text" id="text">
  <input type="submit" value="发送数据" onclick="send()">
  <div id="msg"></div>
</body>
<script>
var isSupport;

if (typeof WebSocket != 'undefined') {
    isSupport = true;
} else {
    isSupport = false;
}

if (isSupport == true) {
    var msg = document.getElementById("msg");
    var wsServer = 'ws://192.168.1.1:9501';
    var websocket = new WebSocket(wsServer);
    websocket.onopen = function (e) {
        console.log("websocket server open.");
    };
    
    websocket.onmessage = function (e) {
        msg.innerHTML += e.data +'<br>';
    }
    
    websocket.onclose = function (e) {
        console.log("websocket server close.");
    };
    
    
}

function send() {
    if (isSupport == true) {
        var text = document.getElementById('text').value;
        document.getElementById('text').value = ''; //向服务器发送数据
        websocket.send(text);
    } else {
        alert("浏览器不支持WebSocket!");
    }
}

</script>
</html>

 

阳光部落原创,更多内容请访问http://www.sunbloger.com/

在XAMPP中为PHP安装YAML扩展

YAML 简介

YAML(是 YAML Ain’t Markup Language 的缩写,尾音的发音类似 Camel)是一种序列化数据的语言(类似 JSON 和 XML ),使用轻量高可读性的语法描述 list 和 dict 等数据结构。

在 XAMPP 中安装 YAML 扩展

首先,根据你本地的 PHP 版本,去 http://pecl.php.net/package/yaml/ 下载 dll。

将下载的压缩包解开后,把其中的 php_yaml.dll 拷贝到你的 php 扩展目录下(例如:C:\xampp\php\ext)。并将压缩包中的 yaml.dll 拷贝到你的 XAMPP 根目录下。然后重启 apache,通过 phpinfo() 查看是否安装成功。

阳光部落原创,更多内容请访问http://www.sunbloger.com/

用Python3提取网页中的超链接

最近有朋友给我指出,我此前写的博文《用Python提取网页中的超链接》(原文地址:http://www.sunbloger.com/article/442.html)中,给出的代码在Python3下运行报错。下面给出在Python3的代码写法:

import urllib.request
import re
 
url = 'http://www.sunbloger.com/'
 
req = urllib.request.urlopen(url)
doc = req.read()
doc = doc.decode('utf-8')
 
links = re.findall(r'href\=\"(http\:\/\/[a-zA-Z0-9\.\/]+)\"', doc)
for a in links:
    print(a)

 

阳光部落原创,更多内容请访问http://www.sunbloger.com/

汇总PHP最常见的四种排序算法

PHP最常见的四种排序算法分别是:冒泡排序法,选择排序法、插入排序法和快速排序法。下面我们就分别给出四种排序算法的实现代码,供大家参考。

1.冒泡排序法

<?php
function bubble_sort($array)
{
    $count = count($array);
    if ($count == 0) {
        return false;
    }
    for ($i=0; $i<$count; $i++) {
        for ($k=$count-1; $k>$i; $k--) {
            if ($array[$k] < $array[$k-1]) {
                $tmp = $array[$k];
                $array[$k] = $array[$k-1];
                $array[$k-1] = $tmp;
            }
        }
    }
    return $array;
}

$a = array(2, 5, 1, 3, 4);
$a = bubble_sort($a);
var_dump($a);
?>

 

2.选择排序法

<?php
function select_sort($array)
{
    $len = count($array);
    for($i=0; $i<$len-1; $i++) {
        $p = $i;
        for($j=$i+1; $j<$len; $j++) {
            if($array[$p] > $array[$j]) {
                $p = $j;
            }
        }
        if($p != $i) {
            $tmp = $array[$p];
            $array[$p] = $array[$i];
            $array[$i] = $tmp;
        }
    }
    
    return $array;
}

$a = array(2, 5, 1, 3, 4);
$a = select_sort($a);
var_dump($a);
?>

 

3.插入排序法

<?php
function insert_sort($array)
{
    $len = count($array);
    for($i=1; $i<$len; $i++) {
        $tmp = $array[$i];
        for($j=$i-1; $j>=0; $j--) {
            if($tmp < $array[$j]) {
                $array[$j+1] = $array[$j];
                $array[$j] = $tmp;
            } else {
                break;
            }
        }
    }
    
    return $array;
}

$a = array(2, 5, 1, 3, 4);
$a = insert_sort($a);
var_dump($a);
?>

 

4.快速排序法

<?php
function quick_sort($array)
{
    $len = count($array);
    if ($len <= 1) {
        return $array;
    }
    
    $base = $array[0];
    
    $left = array();
    $right = array();
    for ($i=1; $i<$len; $i++) {
        if($base > $array[$i]) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }
    $left = quick_sort($left);
    $right = quick_sort($right);
    
    return array_merge($left, array($base), $right);
}

$a = array(2, 5, 1, 3, 4);
$a = quick_sort($a);
var_dump($a);
?>

 

阳光部落原创,更多内容请访问http://www.sunbloger.com/

在CentOS环境为PHP安装Memcached扩展

首先,安装PHP的Memcached扩展前,要先安装其所依赖的libmemcached,方法如下:

# wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
# tar zxvf ./libmemcached-1.0.18.tar.gz
# cd libmemcached-1.0.18
# ./configure --prefix=/usr/local
# make
# make install

 

libmemcached安装完毕后,就可以开始安装Memcached扩展了,方法如下:

# wget https://pecl.php.net/get/memcached-2.2.0.tgz
# tar zxvf ./memcached-2.2.0.tgz
# cd memcached-2.2.0

 

解压缩后,我们需要先修改一下php_libmemcached_compat.h文件
将#include 的路径修改成#include </usr/local/include/libmemcached/memcached.h>然后再继续编译安装

# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --disable-memcached-sasl
# make
# make install

 

最后,还要修改php.ini文件,加入extension=memcached.so并重启php-fpm即可。

阳光部落原创,更多内容请访问http://www.sunbloger.com/

用 MiniFramework 快速构建 REST 风格的 API 接口

MiniFramework 是一款遵循 Apache2 开源协议发布的,支持 MVC 和 RESTful 的超轻量级 PHP 开发框架。

通过 MiniFramework 内置的 REST 接口功能,我们可以很轻松的快速构建起基于 REST 风格的 API 接口,特别是在开发 iOS 和 Android 手机客户端应用时,服务器端的 API 接口是否灵活高效,直接影响着手机应用的体验。

下面介绍一下如何使用 MiniFramework 开发 REST 风格的 API 接口。

第一步,我们下载最新 MiniFramework 1.0.2 版本

下载地址是:https://github.com/jasonweicn/MiniFramework/archive/1.0.2.zip

下载并解压缩后,会看到里面有 App 和 MiniFramework 两个目录,App 目录是一个附带的应用 demo,MiniFramework 目录是框架核心文件。

第二步,我们在 Apache 或 Nginx 中新建一个站点,并将站点的根目录指向 App/Public 这个目录。

设置好站点根目录后,我们可以测试一下,用浏览器访问下面的 URL 地址:

http://你的域名/index.php?c=index&a=index

如果可以显示“Hello World!”,说明站点已经部署成功了。

第三步,为了优化访问 URL 访问的便捷性,我们要给站点设置伪静态规则。

如果你用的是 Apache,那么附带的应用 demo 中已经提供了 .htaccess 文件,不需要额外的设置了。

如果你用的是 Nginx,那么需要在 nginx.conf 中,向对应站点的 server{} 段中,增加下面的代码:

location / {
    index  index.html index.php;
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php last;
    }
}

 

保存后,别忘记重启 Nginx 让配置生效。

经过上述配置后,用浏览器访问下面的 URL 地址:

http://你的域名/index/index

如果可以显示“Hello World!”,那就说明伪静态也配置成功了。

第四步,创建 API 程序

找到 App/Api 目录,这里是存放 API 接口的地方,在里面已经附带了一个名为 Version.php 的 demo,你可以参考这个文件的代码,编写自己的 API,比如我们创建一个名为 User.php,里面放置 get、post、put 和 delete 四个方法,分别对应 REST 中的 GET、POST、PUT 和 DELETE 请求。代码如下:

<?php
//首先要声明当前文件的命名空间为 App\Api
namespace App\Api;
 
//还要引入 Mini\Rest
use Mini\Rest;
 
class User extends Rest //必须要继承Rest类
{
    /**
     * 初始化
     */
    function _init()
    {
        //do something...
    }
    
    /**
     * GET
     */
    function get()
    {
        //我们临时构建一个用户列表数组,在你的业务代码中或许应该通过模型从数据库中读取
        $userlist = array(
            array('id'=>1, 'name'=>'user1'),
            array('id'=>2, 'name'=>'user2'),
            array('id'=>2, 'name'=>'user3')
        );
        
        //将$userlist通过responseJson()方法输出为JSON
        $this->responseJson(200, 'success', $userlist);
    }
    
    /**
     * POST
     */
    function post()
    {
        //获取POST参数
        $params = $this->params->getParams();
        
        //do something...
    }
    
    /**
     * PUT
     */
    function put()
    {
        //获取PUT参数(POST和PUT参数均可通过此方法获得)
        $params = $this->params->getParams();
        
        //do something...
    }
    
    /**
     * DELETE
     */
    function delete()
    {
        //返回HTTP状态码403(在REST中表示对于拒绝访问)
        $this->responseJson(403);
    }
}

 

创建好上边的 API 后,我们可以测试一下,用浏览器访问下面的 URL 地址:

http://你的域名/api/user

此时的访问请求属于 GET 方式,MiniFramework 会将这个请求映射到我们刚刚创建的 User 类的 get() 方法上,如果一切正常,我们会看到浏览器中显示如下内容:

{"code":200,"msg":"success","data":[{"id":1,"name":"user1"},{"id":2,"name":"user2"},{"id":2,"name":"user3"}]}

 

上边显示的内容就是通过 responseJson() 方法输出的 JSON 字符串了,其中 code 代表这次请求服务器返回的状态代码,msg 是返回的说明,data 里面就是这次请求发出后,服务器返回给客户端的数据了。

我们可以看到,上边 User 类的代码中,在最开始要通过 namespace 来声明当前文件的命名空间,在 MiniFramework 中,默认情况下 API 接口的命名空间统一为 App/Api。

再往下还要通过 use 引入 Mini\Rest,这个是 MiniFramework 的核心类之一,我们创建的 API 接口的 class 必须要继承 Rest。

再往下就是 REST 中经典的 get、post、put 和 delete 四个方法,对于客户端请求类型的映射问题,MiniFramework 会自动帮我们处理好,我们只要专注写好业务逻辑就可以了。

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

书籍制作工具 GITBOOK 的安装方法

GitBook 是一个命令行工具(也是 Node.js 库),让你能够使用 GitHub/Git 和 Markdown 构建出美丽的书籍,可以包含互动的练习。GitBook 支持使用多种语言构建书籍。

GitBook支持输出多种文档格式,如:

静态站点:GitBook默认输出该种格式,生成的静态站点可直接托管搭载Github Pages服务上;
PDF:需要安装gitbook-pdf依赖;
eBook:需要安装ebook-convert;
单HTML网页:支持将内容输出为单页的HTML,不过一般用在将电子书格式转换为PDF或eBook的中间过程;
JSON:一般用于电子书的调试或元数据提取。

GitBook项目官网:http://www.gitbook.io
GitBook Github地址:https://github.com/GitbookIO/gitbook

基本安装

1、Node.js安装
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的, 易于扩展的网络应用。Node.js 借助事件驱动, 非阻塞 I/O 模型变得轻量和高效, 非常适合 run across distributed devices 的 data-intensive的实时应用。

登录Node.js官网http://www.nodejs.org/,下载安装包并安装。

安装完成这后,你可以在终端模式下检验一下:

$ node -v
v0.10.29
看到些提示,就表示你已成功安装上了Node.js。

2、Gitbook安装
Gitbook是从NMP安装的,命令行:

$ npm install gitbook -g
安装完之后,你可以检验下是否安装成功:

$ gitbook -V
0.4.2
如果你看到了与上面类似的版本信息,则表示你已成功完装上了Gitbook。

3、calibre安装
Calibre是一个开源的“一站式”的电子书解决方案,它可以全面满足你的电子书需求。Calibre是免费的,源代码开放,拥有跨平台的设计。

Gitbook会使用其中的ebook-convert功能组件来完成书籍格式的转换。

登录calibre官网http://www.calibre-ebook.com/,下载安装。

至此,书籍制作工具GitBook安装完毕。

原文地址:http://blog.liyibo.org/books-installation-authoring-tool-gitbook/

SVN版本库迁移服务器方法

首先,在旧服务器上导出所有版本库

svnadmin dump /var/svn/project > /var/svn/project.dump

 

然后,将导出的 dump 文件拷贝到新服务器上,并在新服务器上创建同名的版本库

svnadmin create project

 

用 load 命令将 dump 文件还原到新服务器上的同名版本库里

svnadmin load project < project.dump

 

最后,别忘记参照旧服务器,去设置新服务器的 authz 和 serve.conf 等设置

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

解决Cacti监控大内存时数据显示nan的问题

通过 Cacti 监控服务器内存使用情况时,Memory Usage 图表中,可能会出现 Cache Memory 或其他数据的值显示为 nan 的情况。出现这种情况大多是由于服务器内存较大,超出了 Cacti 数据模板中 10G 的预设上限值,我们可以通过修改此预设值来解决这个问题,下面是具体修改方法。

首先,登录 Cacti 后,进入到 Console > Data Templates 中,找到和内存监控相关的三个模板,分别是:“ucd/net – Memory – Buffers”、“ucd/net – Memory – Cache”和“ucd/net – Memory – Free”。

然后,逐一修改三个这三个模板中的“Maximum Value”,将这个值扩大至1000000000(100G)。

最后,在修改完模板后,还需要在 Cacti 中将 Memory Usage 相关的图表和数据源(Data Sources)删除重新创建,重建后稍等片刻,待下一次数据抓取后,就会看到原本显示 nan 地方现在都可以正常显示内存数据了。

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

用PHP从本地提取视频并向浏览器输出的方法

有时,在一些特殊场景中,我们需要访问视频时,需要预先通过PHP做一些校验,校验通过后,才允许将视频数据输出给浏览器。

下面这段代码实现了用PHP从本地提取视频文件,并通过header函数以字节的方式向浏览器输出视频数据流。

<?php

//需要下载的文件
$file_name = 'test.mp4';

//下载文件必须先要将文件打开,写入内存
$fp = fopen($file_name, 'r+');

//判断文件是否存在
if (!file_exists($file_name)) {
    echo "文件不存在";
    exit();
}

//判断文件大小
$file_size = filesize($file_name);

//返回的文件
header('Content-type: application/octet-stream');

//按照字节格式返回
header('Accept-Ranges: bytes');

//返回文件大小
header('Accept-Length: ' . $file_size);

//弹出客户端对话框,对应的文件名
header('Content-Disposition: attachment; filename=' . $file_name);

//防止服务器瞬时压力增大,分段读取
$buffer = 4096;

while(!feof($fp)) {
    $file_data = fread($fp, $buffer);
    echo $file_data;
}

//关闭文件
fclose($fp);

?>