本文首先将对Workerman有一个简单的认知介绍,然后通过我遇到过的一个小项目捋一遍用Workerman来快速实现Socket服务。

1. 知识储备

在开始使用workerman之前,可能需要了解这些:

  • 网络通讯协议(HTTP、TCP等)
  • 进程和线程
  • 了解workerman是什么
  • Linux与Windows
  • ……

Workerman官方的解释:http://doc.workerman.net/315119

2. Workerman vs Swoole

Swoole是个好东西,拟补了PHP的很多空白,功能上也会比workerman多,C拓展方式性能也没得说,但是就是相比workerman门槛高一点(官方文档不清晰是一方面)。

Workerman纯PHP编写,文档做得很好,上手非常简单,可以快速开发功能,性能也很不错。Workerman还有一个分支项目GatewayWorker,如果项目是长连接并且需要客户端与客户端之间通讯,可以使用GatewayWorker更快速实现功能。

3. 知识概览

WorkerMan中有两个重要的类Worker与Connection。

3.1 Worker类

Workerman中的端口监听通过Worker类实现

Worker类有这么些个回调函数:

  • onWorkerStart Worker启动时
  • onWorkerReload Worker收到reload信号后
  • onConnect 建立链接时(TCP三次握手完成后)触发
  • onMessage 客户端通过链接发来数据时(Workerman收到数据时)
  • onClose 客户端连接与Workerman断开时
  • onBufferFull 超过缓冲区大小限制时
  • onBufferDrain 应用层发送缓冲区数据全部发送完毕后
  • onError 当客户端的连接上发生错误时

Worker类有这么些个接口:

  • runAll 运行所有Worker实例
  • stopAll 停止当前进程(子进程)的所有Worker实例并退出
  • listen 用于实例化Worker后执行监听

3.2 Connection类

每个客户端连接对应一个Connection对象。

Connection类有这么些个回调函数:

  • onMessage 作用与Worker::$onMessage回调相同,区别是只针对当前连接有效
  • onClose 此回调与Worker::$onClose回调作用相同,区别是只针对当前连接有效
  • onBufferFull 作用与Worker::$onBufferFull回调相同,区别是只针对当前连接起作用
  • onBufferDrain 作用与Worker::$onBufferDrain回调相同,区别是只针对当前连接起作用
  • onError 作用与Worker::$onError回调相同,区别是只针对当前连接起作用

Connection类有这么些个接口:

  • send 向客户端发送数据
  • getRemoteIp 获得该连接的客户端ip
  • getRemotePort 获得该连接的客户端端口
  • close 全的关闭连接
  • destroy 立刻关闭连接
  • pauseRecv 使当前连接停止接收数据
  • resumeRecv 使当前连接继续接收数据
  • pipe 将当前连接的数据流导入到目标连接

3.3 其它

  • AsyncTcpConnection类
  • Timer定时器类
  • WebServer

4. 开始实现

4.1 确定需求

首先明确需要做什么,要达到什么目的;以之前做过的一个项目为例,实现一个可以通过APP实时控制的音乐播放系统,大概是以下的模式:
播放器架构
要做到实时推送操作指令达到控制音乐的播放,首先要接收到移动端发来的指令,然后分析,根据指令操纵H5播放器,返回结果,通知移动端。在这里,我们用了WebSocket在浏览器与Server建立了连接来操纵H5播放器,因为移动端不是我们开发,以及这是一个局域网项目,为了使项目更简单,移动端采用了HTTP接口调用的方式(这种方式,在操纵完播放器返回时,我们需要做点手脚,以及会有一定的性能损失),当然最方便最好的就是移动端跟Server建立长连接。

4.2 安装准备

明确了需求,确定了技术方向后,就可以开始干了。虽然workerman有windows版本,不过在windows上是阉割版,能用Linux还是linux。

安装流程:http://doc.workerman.net/315114
windows版本的说明:http://www.workerman.net/windows

4.3 一个简单Server

以WebSocket为例新建一个简单的Server:

1)新建一个项目目录

2)引入workerman(Workerman/Autoloader.php)

require_once ‘/your/path/Workerman/Autoloader.php’;

3)确定协议

目前WorkerMan支持HTTP、Websocket、Text文本协议(WorkerMan中自定义的一个协议,格式为文本+换行),如果需要使用其它协议,可以参照 http://doc.workerman.net/315123 通讯协议一章开发自己的协议。
这里我们以 Websocket 协议为例。

4)编写程序start_websocket.php

一个简单的示例:

<?php
use Workerman\Worker;
require_once __DIR__ . '/path/to/Workerman/Autoloader.php';

// 创建一个Worker监听端口,使用websocket协议通讯
$ws_worker = new Worker('websocket://0.0.0.0:2345');

$ws_worker->count = 1;// 进程数
$ws_worker->name = 'mPlayer';// worker名称

//Worker启动后立即执行的回调函数
$ws_worker->onWorkerStart = function($ws_worker)
{
    // ...
};

// 连接建立时触发
$ws_worker->onConnect = function($connection)use($ws_worker)
{
    // 设置连接的onMessage回调
    $connection->onMessage = function($connection, $data)
    {
        $connection->send('receive success');
    };
    // ...
};

// 当收到客户端发来的数据时
$ws_worker->onMessage = function($connection, $data)
{
    $connection->send('receive success');
    // ...
};

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

5)运行Server

Linux下:
以debug(调试)方式启动:php start.php start
以daemon(守护进程)方式启动:php start.php start -d

Windows下:
cmd命令行启动:php start_websocket.php

6)进行测试

进行测试,可以抓包看看请求的状况。