您现在的位置是:网站首页>>PHP>>webSocket

webSocket在服务端(PHP)介绍

发布时间:2020-01-08 18:52:16作者:wangjian浏览量:127点赞量:0

    之前我们已经简单的了解过了websocket的使用了

    简单使用:https://www.wj0511.com/site/detail.html?id=248

    如果需要使用websocket的话,php需要安装swoole拓展,安装swoole拓展可以参考

    windows下安装swoole拓展:https://www.wj0511.com/site/detail.html?id=246

    linux下安装swoole拓展:https://www.wj0511.com/site/detail.html?id=247

    这里我来详细的说明下websocket在服务端所需要使用到的方法及属性

    一:创建websocket服务器对象

    在使用websocket之前首先需要创建一个websocket服务器对象

    $server = new \swoole_websocket_server($host, $port);

    参数说明:

    $host:websocket需要监听的IP,0.0.0.0 表示监听所有IP地址

    $port:websocket需要监听的端口号

    根据如上如:

    $server = new \swoole_websocket_server('0.0.0.0', '8888');

    如上代码表示创建一个websocket服务器对象并监听0.0.0.0:8888

    二:设置运行参数

    创建websocket服务器对象后,我们可以设置websocket运行时的各项参数,这时候使用到set方法

    $server->set(array $setting);

    参数说明:

    $server:创建websocket服务器对象返回的对象

    $setting:websocket运行各项参数,$setting是一个数组参数

    常见的运行参数有:

    1:事件处理线程的数量(reactor_num)

    'reactor_num' => 2, //通过此参数来调节主进程内事件处理线程的数量,以充分利用多核。默认会启用CPU核数相同的数量。一般设置为CPU核数的1-4倍

    2:设置启动的Worker进程数(worker_num)

    'worker_num' => 4, //如果业务代码是全异步非阻塞时,这里设置为CPU的1-4倍最合理,如果业务代码为同步阻塞,需要根据请求响应时间和系统负载来调整

    3:设置worker进程的最大任务数(max_request)

    'max_request' => 50, //此参数表示worker进程在处理完n次请求后结束运行。并重新创建一个worker进程。此选项用来防止worker进程内存溢出

    4:设置最大最大允许的连接数(max_connection)

    'max_connection' => 1000, //此参数用来设置Server最大允许维持多少个TCP连接。超过此数量后,新进入的连接将被拒绝

    5:数据包分配模式(dispatch_mode)

    'dispatch_mode' => 1, //1平均分配,2按FD取模固定分配,3抢占式分配,默认为取模(dispatch=2)

    6:当dispatch_mode参数设置为1和3时,这时候系统会默认关闭onConnect/onClose事件,这时候如果你需要onConnect/onClose事件,这时候你需要设置enable_unsafe_event为true

    'enable_unsafe_event' => true,

    7:日志文件路径(log_file)

    'log_file' => '/data/log/swoole.log', // 指定swoole错误日志文件地址,默认错误日志会打印到页面上

    8:设置websocket错误日志打印等级(log_level),范围是0-5

    'log_level' => 1, //低于log_level设置的日志信息不会抛出

    9:进程的PID存储文件地址(pid_file)

    'pid_file' => '/data/log/server.pid',

    10:启动TCP-Keepalive死连接检测(open_tcp_keepalive)

    'open_tcp_keepalive' => 1

    11:指定秒中如果没有数据请,对此连接进行检测(tcp_keepidle)

    'tcp_keepidle' => 5,

    12:超过指定探测次数,关闭此连接(tcp_keepcount)

    'tcp_keepcount' => 5,

    13:设置探测的间隔事件,单位为秒(tcp_keepinterval)

    'tcp_keepinterval' => 3

    14:心跳检测机制

    (1)heartbeat_check_interval

    'heartbeat_check_interval' => 5, //心跳检测,此选项表示每隔多久轮循一次,单位为秒

    (2)heartbeat_idle_time

    'heartbeat_idle_time' => 15, //心跳检测,连接最大允许空闲的时间

    15:守护进程化(daemonize)

    'daemonize' => 1, //正常情况下执行websocket脚本时,会在命令行显示运行过程,当此参数设置为1时,这时候websocket脚本将转入后台作为守护进程运行

    如上就是websocket一些常用的运行参数,使用set方法设置运行参数简单实例如下

    $server->set([
        'max_request' => 50,
    ]);

    如果你不想要自己进行设置运行参数的话,可以不适用set方法,这时候系统会使用默认的运行参数

    三:注册websocket事件的回调函数

    在websocket中我们可以使用on方法来注册指定事件的回调函数

    $server->on(string $event, mixed $callback);

    参数说明:

    $server:创建websocket服务器对象返回的对象

    $event:需要注册的事件名称,此参数需要将事件名称前面的on字符去除

    $callback:回调的PHP函数,可以是函数名的字符串,类静态方法,对象方法数组,匿名函数

    常见的事件有:

    1:onStart:websocket启动后事件,onStart回调中,仅允许echo、打印Log、修改进程名称。不得执行其他操作

    如:

    $server->on('start', function($server) {
    echo 'server 启动';
    echo "\n";
    echo 'websocket进程ID为' . $server->master_pid;
    });

    2:onHandShake:WebSocket建立连接后进行握手事件,WebSocket服务器已经内置了握手事件,如果用户希望自己进行握手处理,可以设置onHandShake事件回调函数

    这里注意,如果你设置了握手事件的话,这时候你就不会再触发onOpen事件,这时候你就需要手动去触发onOpen事件

    如:

    $server->on('handshake', function($request, $response) use ($server) {
    echo '握手成功';
    defaultHandshake($request, $response);
    //手动调用onOpen事件
    $server->defer(function() use ($server, $request) {
                onOpen($server, $request);
        });
    });
    //默认的握手处理
    function defaultHandshake($request, $response) {
    // websocket握手连接算法验证
            $secWebSocketKey = $request->header['sec-websocket-key'];
            $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
            if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
                $response->end();
                return false;
            }
            $key = base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
            $headers = [
                'Upgrade' => 'websocket',
                'Connection' => 'Upgrade',
                'Sec-WebSocket-Accept' => $key,
                'Sec-WebSocket-Version' => '13',
            ];
            if (isset($request->header['sec-websocket-protocol'])) {
                $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
            }
            foreach ($headers as $key => $val) {
                $response->header($key, $val);
            }
            $response->status(101);
            $response->end();
    }

    3:onOpen:当WebSocket客户端与服务器建立连接并完成握手后会回调此函数

    如:

    $server->on('open', function ($server, $request) {
    echo 'server 连接成功';
    });

    如果你设置了握手的话,可以这样写:

    $server->on('open', function ($server, $request) {
    onOpen($server, $request);
    });
    function onOpen($server, $request) {
    echo 'server 连接成功';
    }

    4:onMessage:当服务器收到来自客户端的数据帧时会回调此函数

    $server->on('message', function ($server, $frame) {
        echo "客户端信息为" . $frame->data;
    });

    5:onRequest:如果设置了onRequest回调,WebSocket也可以同时作为http服务器,及当直接在浏览器访问时,onRqeust事件会触发,如果不设置的话,收到http请求后会返回http 400错误页面

    $server->on('request', function ($request, $response) {
       echo 'server 路由响应'
    });

    6:onClose:webscoket客户端关闭连接后触发

    //监听WebSocket连接关闭事件
    $server->on('close', function ($server, $fd) {
        echo "客户端进程" . $fd . '关闭';
    });

    7:onShutdown:在websocket服务正常关闭时触发

    $server->on('shutdown', function ($server) {
        echo 'websocket服务端关闭';
    });

    如上就是在websocket中常见的事件

    四:启动websocket服务器

    $server->start();

    当我们设置好websocket的运行参数和事件回调之后执行如上方法,这时候我们的websocket服务器就启动了

    五:向客户端发送消息

    在websocket中使用push方法项客户端发送消息

    $server->push($fd, $data);

    参数说明:

    $fd:客户端连接的ID

    $data:要发送的数据内容

    六:在websocket中常见的属性和方法

    1:server对象可以获取的属性值和方法

    (1):获websocket所有的运行参数

    $server->setting

    (2):获取websocket的主服务进程ID

    $server->master_pid

    (3):获取所有的客户端连接ID

    [1]

    $server->getClientList(0, 10) //参数1表示骑士的客户端连接ID,参数2表示每页显示的条数

    [2]

    foreach($server->connections as $fd)
    {
    echo $fd;
    }

    这里推荐使用$server->connections获取客户端连接

    (4):判断指定客户端连接ID是否存在

    $server->exist($fd)

    (5)判断指定客户端连接ID是否为已完成握手的WebSocket客户端连接

    $server->isEstablished($fd)

    (7):我们可以主动将指定客户端连接关闭

    $server->close($fd);//关闭指定客户端连接

    2:request对象可以获取的属性值和方法

    (1):获取当前连接的客户端连接ID

    $request->fd

    (2):获取客户端请求传递的参数

    $request->get

    如客户端地址为ws://127.0.0.1:8888?id=2时上面获取的方法返回为:

    [
        'id' => 2
    ]

    (3)获取相关的服务器信息

    我们可以获取到客户端请求的路由

    $request->server['request_uri']

    如客户端地址为ws://127.0.0.1:8888/test时上面获取的方法返回为 /test

    (4):获取客户端的请求头信息


    $request->header

    当我们在客户端实例化websocket增加第二个参数时如

    var wsServer = 'ws://127.0.0.1:8888';
    var websocket = new WebSocket(wsServer, 'public');

    这时候在服务端我们就可以使用如下方法获取到public值

    $request->header['sec-websocket-protocol']

    如上就是websocket在服务端的简单介绍了

0 +1