swoole学习(二)—-搭建server和client

by admin on 2019年3月9日

1.搭建server

[toc]
swoole算是nodejs在php中的一种完成,异步响应请求,质量超强

小说导读:

websocket的原理和应用

  1.1搭建server.php

    1.搭建websocket服务器,首先建立 server.php 文件,

    

 1 <?php
 2 $server = new swoole_websocket_server('0.0.0.0', 9502);// 创建swoole的websocket实例 其中 0.0.0.0 代表监听所有回路 包括127.0.0.1 和 192.168.*.* 和 外部IP, 端口是9502
 3 
 4 //监听打开事件
 5 $server->on('open', function ($server, $request){
 6    var_dump($request->fd, $request->get, $request->server);
 7    $server->push($request->fd, "我是open\n");
 8 });
 9 
10 //监听消息事件
11 $server->on('message', function ($server, $message){
12     echo "Message: {$message->data}\n";
13     $server->push($message->fd, "服务器给的: {$message->data}");
14 });
15 
16 //监听关闭事件
17 $server->on('close', function ($server, $fd){
18     echo "客户端: {$fd} 关闭了";
19 });
20 
21 $server->start();

    $server->push(“客户端ID”,
“推送消息”); 
本条点子是server向client推送新闻的办法;

    server 的 on 事件监听有 open : 连接成功事件

                message : 收到新闻事件

                close : 客户端关闭事件

    2.运行server.php文件 php server.php     bf88必发唯一官网 1

1 安装准备

  •  一、概述-what’s
    WebSocket?
  •  二 、运维在浏览器中的WebSocket客户端+使用ws模块搭建的简短服务器
  •  三、Node中的WebSocket
  •  四、socket.io
  •  ⑤ 、扩大阅读

在三番7次本文以前,让大家领悟下websocket的法则:

2.搭建client

1.1 安装swoole前务必保障系统已经安装了下列软件

php-5.3.10 或更高版本
gcc-4.4 或更高版本
make
autoconf
pcre (centos系统能够执行命令:yum install pcre-devel)

 

websocket通讯协议完成的是根据浏览器的原生socket,这样原本唯有在c/s情势下的大方支付情势都能够搬到web上来了,基本正是因而浏览器的扶助在web上落实了与劳务器端的socket通讯。

  2.1 搭建client.html

    1.成立client.html,首要利用 js 的 WebSocket() 

    

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 
 9 </body>
10 <script>
11     var wsServer = 'ws://192.168.33.10:9502';
12     var websocket = new WebSocket(wsServer);
13     websocket.onopen = function (evt) {
14         console.log("连接到服务器");
15     };
16 
17     websocket.onclose = function (evt) {
18         console.log("连接关闭");
19     };
20 
21     websocket.onmessage = function (evt) {
22         console.log('收到服务器信息' + evt.data);
23     };
24 
25     websocket.onerror = function (evt, e) {
26         console.log('错误信息: ' + evt.data);
27     };
28 </script>
29 </html>

    2.参数表达: var wsServer =
‘ws://192.168.33.10:9502’; 

          ws:
代表采用websocket共同商议

          ip地址
是server的地址

    3.监听事件 onopen
: 客户端连接到服务器的时候接触

         onclose :
客户端关闭的时候接触

         onmessage :
收到服务器新闻的时候接触

         onerror :
产生错误的时候接触,包含延续错误,发送、接收消息的时候出现错误触发

1.2 下载并解压

下载地址
跻身页面后选拔download链接下的tar.gz的压缩包
下载源代码包后,解压
tar xzvf xxx.tar.gz,
在极端进入源码目录,执行上边包车型大巴授命进行编写翻译和安装
cd swoole
phpize
./configure –enable-swoole-debug
make
sudo make install

编写翻译参数依据自身的急需选择,详情参见官方文书档案。

一、概述-what’s WebSocket?

1.1 为何大家须要WebSocket那样的实时的通信协议?

WebSocket是web通讯格局的一种,像大家熟识的HTTP协议也是web通讯形式的一种。不过大家了然HTTP协议是一种无状态的磋商,其服务端本人不拥有识别客户端的力量,必须借助外部的有的音信比如说session和cookie,才能与一定的客户端保持通讯。也便是说大家所发送的每三个HTTP的呼吁都会带上请求头中有些应和的音讯还有cookie,这肯定会追加大家传输的新闻的体积从而推动一定的互连网延迟,对于部分对通讯的实时性供给比较高的应用来说正是不行忍受的了,比如说聊天程序还是是运维在浏览器中的实时小游戏。最郁闷的却依然那一个头信息和cookie往往对于服务器响应客户端的乞求来说是多余的,也正是说就算自个儿每一个请求都带了这几个音讯,可是服务器与客户端的互相进度中恐怕根本用不上那一个音信。

为了句斟字酌HTTP请求的那种网络延迟的景况,也应运而生了一部分适应不相同供给的任何的[web通信]方式,比如说:轮询,长轮询(long-polling),数据流,伊夫ntSouce等等,WebSocket就是其中一种。

实际当先6/10基于因特网(或许局域网)的互联网链接日常都包括长连接和根据TCP套接字的双向音讯交流。可是TCP协议是属于最底部的网络通讯协议了,让部分无法相信的客户端脚本去做客底层的TCP套接字显著是不太安全的,因而WebSocket达成了一种较为安全的方案,它同意客户端脚本在客户端和支撑WebSocket共同商议的服务器之间成立双向的套接字连接。从而使实时通讯的少数网络操作变得简单。

1.2 WebSocket是怎么样工作的?

小编们领略了WebSocket的重点作用是,允许服务器端与客户端进行全双工(full-duplex)的实时通讯。那里有个例子尤其好:HTTP协议像发电子邮件,发出后必须等待对方回信;WebSocket则是像打电话,服务器端和客户端能够而且向对方发送数据,它们之间存着一条持续打开的数据通道。

我们先看一下二个基于WebSocket协议通讯的请求头和响应头(下边简单实例中的八个消息头):

bf88必发唯一官网 2

中间与WebSocket协议相关的音信:

bf88必发唯一官网 3

1 Upgrade:websocket-------HTTP1.1协议规定,Upgrade头信息表示将通信协议从HTTP/1.1转向该项所指定的协议;
2 Connection:Upgrade------表示浏览器通知服务器,如果允许,就将通信协议升级到websocket协议;
3 Origin------------------用于验证浏览器域名是否在服务器许可的范围内;
4 Sec-WebSocket-Key-------则是用于握手协议的密钥,是base64编码的16字节随机字符串;
5 Sec-WebSocket-Accept----是服务器在浏览器提供的Sec-WebSocket-Key字符串后面,添加“258EAFA5-E914-47DA-95CA-C5AB0DC85B11” 字符串,然后再取sha-1的hash值。浏览器将对这个值进行验证,以证明确实是目标服务器回应了webSocket请求;
6.Sec-WebSocket-Location--一般情况下还有这个响应消息头用来表示进行通信的WebSocket网址,这里面可能是因为我例子中设置了127.0.0.1,所以这个信息省略掉了。

bf88必发唯一官网 4

客户端通过叁个WebSocket握手的经过建立1个WebSocket连接。整个经过看起来是其一样子的:

bf88必发唯一官网 5

形成握手以往,WebSocket探讨就在TCP协议之上,客户端和服务器端就足以起来传送数据了。

websocket协和式飞机用ws表示,加密的websocket协议用wss协议,就像是一般的HTTP协议用http表示,加密的HTTP协议用https表示无差异。

上边大家就由此一些实例看一下websocket的分歧实现是什么利用的。

WebSocket没有打算在HTTP之上模拟server推送,而是径直在TCP之上定义了帧协议,因而WebSocket能够帮衬双向的通讯。

3.测试连接

1.3 编写翻译安装成功后,修改php.ini

在php.ini中加入 extension=swoole.so
通过在命令行使用 php-m查看,是或不是安装了swoole

只顾:如通重新编写翻译的话须求 make clean

贰 、 运转在浏览器中的WebSocket客户端+使用ws模块搭建的简便服务器

swoole学习(二)—-搭建server和client。咱俩能够通过跑起来那个简单的实例看一下什么编写运转在浏览器中的WebSocket客户端,并且看它是什么样与劳务器端交互的。

2.1 运转实例

咱俩把客户端代码和服务端代码准备好,然后运转服务器监听端口,比如说8080,再然后运行大家的客户端代码即可见到效率。

咱俩的客户端代码写在html文件中:

bf88必发唯一官网 6 View Code

[查看源码]

咱俩因此它创设连接并且监听open和messege等事件,与此同时,大家想要获得服务器的响应。服务器端的js代码:

bf88必发唯一官网 7 View Code

[查阅源码]

那个简单的websocket服务器使用了[ws模块],倘诺没有设置过,要先安装一下:

1 sudo npm install ws

接下来在大家的命令行执行:

1 node simpleWSserver.js

大家的服务器运维之后,大家运维客户端代码能够看来:

浏览器:

bf88必发唯一官网 8        

命令行:

bf88必发唯一官网 9

全体进程看起来是其一样子的:

bf88必发唯一官网 10

2.2 运维在浏览器中的websocket客户端

 大家在浏览器中的websocket主要做的事体只是是以下多少个:

1 建立连接和关闭连接 
2 发送数据和接收数据
3 处理错误

对应的会触发之下的风浪:

1 onopen
2 onmessage
3 onclose
4 onerror

2.2.1 建立连接和倒闭连接

司空眼惯我们新建了贰个WebSocket的实例就足以创制四个接连:

1 if(window.WebSocket != undefined) {
2     var socket = new WebSocket("ws://127.0.0.1:8080/");
3 }

确立连接之后的WebSocket实例有四个readyState属性,用来标识当前的景象:

0-正在连接
1-连接成功
2-正在关闭
3-关闭成功

总是成功后会触发onopen事件,那时我们就能够向服务器发送数据了:

1 var onOpen = function() {
2       console.log("Socket opened.");
3       socket.send("Hi, Server!");
4  }
5 socket.onopen = onOpen;

要是关闭连接的话就会出发onclose事件:

1 var onClose = function() {
2         console.log("Socket closed.");
3   }
4 socket.onclose = onClose;

2.2.2 发送数据和接收数据

在延续建立成功后触发的onopen事件中大家通过send()方法发送数据给服务器:

1 socket.send("Hi, Server!");

除了发送字符串类型的数量,也得以应用 Blob 或 ArrayBuffer
对象发送二进制数据。不仅如此,咱们还是能够发送JSON数据:

bf88必发唯一官网 11

 1  var onOpen = function() {
 2       var msg = {
 3          type: "message",
 4          text: "something",
 5          id:   "number",
 6          date: Date.now()
 7       };
 8 
 9    // Send the msg object as a JSON-formatted string.
10    socket.send(JSON.stringify(msg));
11   }
12  socket.onopen = onOpen;

bf88必发唯一官网 12

那会儿会接触服务器端的message事件:

1 ws.on('message', function incoming(message) {
2     console.log('received: %s', message);
3   });

并且,服务器端发来消息的时候:

1 ws.send('something');

也会触发客户端的onmessage事件:

1 var onMessage = function(data) {
2         console.log("We get signal:");
3         console.log(data);
4   }
5 socket.onmessage = onMessage;

2.2.3 处理错误

暴发的错误会触发onerror事件:

1 var onError = function() {
2      console.log("We got an error.");
3  }
4 socket.onerror = onError;

 

首先来介绍下websocket客户端与服务端建立连接的历程:

  3.1客户端连接

  bf88必发唯一官网 13

  输出符合规律

2 营造Swoole基本实例

三、Node中的WebSocket

 WebSocket在Node中的完成[WebSocket-Node]使大家能够在Nodejs中选拔websokcet开发客户端和劳务器端实时互动的应用程序。大家能够运作客户端和服务器实时调换随机数的例子看看它是怎么工作的:

发轫服务器:

node socketserver.js

[翻看源码]

开发银行客户端:

node socketclient.js

[翻开源码]

bf88必发唯一官网 14   
 bf88必发唯一官网 15

先用js成立多个WebSocket实例,使用ws协议建立服务器连接,ws://www.cnodejs.org:8088

  3.2服务器连接

  bf88必发唯一官网 16

  出口符合规律!

2.1 tcp服务器实例

(来自w3cschool教程

服务端代码:Server.php

<?php
// Server
class Server
{
    private $serv;

    public function __construct() {
        $this->serv = new swoole_server("0.0.0.0", 9501);
        $this->serv->set(array(
            'worker_num' => 8,
            'daemonize' => false,
            'max_request' => 10000,
            'dispatch_mode' => 2,
            'debug_mode'=> 1
        ));

        $this->serv->on('Start', array($this, 'onStart'));
        $this->serv->on('Connect', array($this, 'onConnect'));
        $this->serv->on('Receive', array($this, 'onReceive'));
        $this->serv->on('Close', array($this, 'onClose'));

        $this->serv->start();
    }

    public function onStart( $serv ) {
        echo "Start\n";
    }

    public function onConnect( $serv, $fd, $from_id ) {
        $serv->send( $fd, "Hello {$fd}!" );
    }

    public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
        echo "Get Message From Client {$fd}:{$data}\n";
    }

    public function onClose( $serv, $fd, $from_id ) {
        echo "Client {$fd} close connection\n";
    }
}
// 启动服务器
$server = new Server();

从代码中可以见见,创立1个swoole_server基本分三步:

  1. 透过构造函数创制swoole_server对象
  2. 调用set函数设置swoole_server的有关安顿选项
  3. 调用on函数设置相关回调函数
    关于set配置选项以及on回调函数的具体表达,请参考作者收拾的swoole文书档案(
    配置选项)
    此处只交付不难介绍。onStart回调在server运维前被调用,onConnect在有新客户端连接过来时被调用,onReceive函数在有数量发送到server时被调用,onClose在有客户端断开连接时被调用。
    那里就足以大体看看哪些选拔swoole:在onConnect处监听新的连日;在onReceive处接收数据并处理,然后能够调用send函数将处理结果发送出去;在onClose随处理客户端下线的事件。

swoole学习(二)—-搭建server和client。客户端的代码:Client.php

<?php
class Client
{
    private $client;

    public function __construct() {
        $this->client = new swoole_client(SWOOLE_SOCK_TCP);
    }

    public function connect() {
        if( !$this->client->connect("127.0.0.1", 9501 , 1) ) {
            echo "Error: {$fp->errMsg}[{$fp->errCode}]\n";
        }
        $message = $this->client->recv();
        echo "Get Message From Server:{$message}\n";

        fwrite(STDOUT, "请输入消息:");  
        $msg = trim(fgets(STDIN));
        $this->client->send( $msg );
    }
}

$client = new Client();
$client->connect();

这里,通过swoole_client创造二个依据TCP的客户端实例,并调用connect函数向内定的IP及端口发起连接请求。随后即可通过recv()和send()八个函数来接受和出殡和埋葬请求。须求注意的是,这里作者使用了默许的一块阻塞客户端,因而recv和send操作都会时有产生网络不通。

选择方式

进去到文件目录,在窗口1先运转php
Serve.php,然后再开二个窗口(窗口2)运转php Client.php
窗口1内容:

# root @ WENGINE in /data/learnSwoole [9:24:57] C:130
$ php Server.php
Start
Get Message From Client 1:ceshi1
Client 1 close connection

窗口2内容:

# root @ WENGINE in /data/learnSwoole [9:23:07] 
$ php Client.php
Get Message From Server:Hello 1!
请输入消息:ceshi1

四、socket.io

今天非常的火的websocket的兑现socket.io同样席卷客户端和劳动器端两片段。它不仅仅简化了接口,使得操作更便于,而且对于那个不帮助WebSocket的浏览器,会活动降为Ajax连接,最大限度地保险了包容性。它的靶子是统一通讯机制,使得全部浏览器和移动设备都得以举办实时通讯。

4.1 socket.io与WebSocket的差距在哪儿呢? 

websocket是浏览器对象,websocket
api是浏览器提要求大家的用来浏览器和服务器实时通讯的接口。

websocket在node中的达成使大家得以付出服务端程序时选择websocket的特性。

在大家运用websocket的时候,因为他是浏览器提供的接口,所以会涉及到部分包容性和协理性的题材。要是我们对先后所运营的环境或局限不是那么掌握的化,那么只怕会产出难点:

[Differences between socket.io and
websocket]
。而socket.io则是进步了的websocket
api。socket.io建立在websocket之上,它在适用的时候利用websocket。

 4.2 socket.io达成聊天室

动用websocket或socket.io可以从一个粗略的聊天室程序起始。对于socket.io来说,那分外简单。

基于node,这里使用express和socket.io:

1 npm install --save express@4.10.2
2 npm install --save socket.io

那便是说大家就足以起来写聊天程序了。它须求的就是1个客户端的闲谈窗口和1个用来接过音信和散发消息的服务器。

咱俩必要八个文本,分别新建:package.json,index.js,index.html.

package.json:

bf88必发唯一官网 17 View Code

index.js:

bf88必发唯一官网 18 View Code

index.html:

bf88必发唯一官网 19 View Code

先运行:

node index.js

在开拓七个

bf88必发唯一官网 20   
 bf88必发唯一官网 21

[查看源代码]

socket.io官网上有很详细的选取方式和课程:[socket.io
doc]

ws初始是一般的websocket连接,wss是高枕无忧的websocket连接,类似于https。

4.总结

  swoole的
websocket
服务器搭建成功,当客户端请求服务器的时候,客户端执行了onopen事件,触发了console.log,服务器端当client连接的时候,触发了onopen,打字与印刷了fd,和客户端请求头信息;

这么就搭建成功了server和client实时双工通讯!
能够做三个实时聊天室,也许弹幕系统,以后渐次学习!

2.2 web服务器

服务端代码 http_server.php

$http = new swoole_http_server("0.0.0.0", 9501);

$http->on('request', function ($request, $response) {
    var_dump($request->get, $request->post);
    $response->header("Content-Type", "text/html; charset=utf-8");
    $response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});

$http->start();

Http服务器只需求关爱请求响应即可,所以只必要监听1个onRequest事件。当有新的Http请求进入就会触发此事件。事件回调函数有1个参数,三个是$request对象,包罗了请求的连带消息,如GET/POST请求的数码。
别的叁个是response对象,对request的响应得以通过操作response对象来成功。$response->end()方法表示输出一段HTML内容,并终止此呼吁。
● 0.0.0.0
表示监听全部IP地址,一台服务器大概同时有四个IP,如127.0.0.1本地回环IP、192.168.1.100局域网IP、210.127.20.2
外网IP,那里也得以单独内定监听三个IP
● 9501 监听的端口,要是被挤占程序会抛出致命错误,中断执行。

五 、扩大阅读

[浏览器对象-WebSocket]

[web通信]

[细说WebSocket]

[WebSocket MDN]

[WebSocket-Node
implementation]

[A Guide For WebSocket]

[socket.IO]

[writing websocket
client]

[deferences between socket.io and
websocket]

[websocket and socketio]

[socket.io application]

客户端与服务端建立握手,发送如下新闻:

2.3 WebSocket服务器

服务端程序代码 ws_server.php

//创建websocket服务器对象,监听0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);

//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
    var_dump($request->fd, $request->get, $request->server);
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

WebSocket服务器是两手空空在Http服务器之上的长连接服务器,客户端首先会发送三个Http的呼吁与服务器实行握手。握手成功后会触发onOpen事件,表示连接已就绪,onOpen函数中得以博得$request对象,包蕴了Http握手的相干消息,如GET参数、Cookie、Http头音信等。
树立连接后客户端与劳务器端就足以双向通讯了。
bf88必发唯一官网,● 客户端向劳动器端发送消息时,服务器端触发onMessage事件回调

服务器端能够调用$server->push()向有些客户端(使用$fd标识符)发送消息
● 服务器端能够设置onHandShake事件回调来手工业处理WebSocket握手
运营程序

客户端的代码

能够使用Chrome浏览器举办测试,JS代码为:

var wsServer = 'ws://127.0.0.1:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
    console.log("Connected to WebSocket server.");
};

websocket.onclose = function (evt) {
    console.log("Disconnected");
};

websocket.onmessage = function (evt) {
    console.log('Retrieved data from server: ' + evt.data);
};

websocket.onerror = function (evt, e) {
    console.log('Error occured: ' + evt.data);
};
  • 不可能直接使用swoole_client与websocket服务器通讯,swoole_client是TCP客户端
  • 务必完毕WebSocket协议才能和WebSocket服务器通讯,能够选取swoole/framework提供的PHP
    WebSocket客户端
  • WebSocket服务器除了提供WebSocket作用之外,实际上也足以处理Http长连接。只供给充实onRequest事件监听即可兑现Comet方案Http长轮询。

关于onRequest回调
swoole_websocket_server 继承自 swoole_http_server

  • 安装了onRequest回调,websocket服务器也能够同时作为http服务器
  • 未安装onRequest回调,websocket服务器收到http请求后会重临http
    400荒谬页面
  • 设若想经过吸收http触发全数websocket的推送,要求注意功能域的题材,面向进程请使用“global”对swoole_websocket_server进行引用,面向对象能够把swoole_websocket_server设置成3个成员属性

能够成立越来越多的劳动器 参照官方文书档案尝试

GET /echo HTTP/1.1

3 使用laravel5.5完毕的前后台通讯实例

重中之重思路是使用php artisan
自行建造命令控打败务端,使用HTML5的websocket实现客户端成效

服务端:app/Console/Commands/Websocket.php内容

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use swoole_http_request;
use swoole_http_response;
use swoole_websocket_server;

class WebSocket extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'websocket 
                            {cmd=start : can use start|stop|status|restart}
                            {--daemon : set to run in daemonize mode}
                            ';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'swoole server control';


    /**
     * server
     *
     * @var swoole_websocket_server
     */
    private $server;

    /**
     *      * TYPE_ADMIN
     *           */
    const TYPE_ADMIN = 0X00;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 处理不同command信息
     *
     * @return mixed
     */
    public function handle()
    {
        $command = $this->argument('cmd');
        $option = $this->option('daemon');

        switch ($command) {
            case 'start':
                $this->initWs($option);
                break;
            case 'stop':
                $res = $this->sendAdminRequest($command);
                if ($res){
                    $this->info('stop the server successfully');
                } else {
                    $this->info('the server is not running');
                }
                break;
            case 'status':
                $res = $this->sendAdminRequest($command);
                if ($res){
                    $this->info($res);
                } else {
                    $this->info('the server is not running');
                }
                break;
            case 'restart':
                $res = $this->sendAdminRequest($command);
                if ($res){
                    $this->info('restart the server successfully');
                } else {
                    $this->info('the server is not running');
                }
                break;
            default:
                $this->info('请按照下面格式输入命令:php artisan websocket {start|stop|status|restart}');
                break;
        }

    }

    //初始化服务端
    public function initWs($daemonize = false) 
    {
        if ($daemonize) {
            $this->info('Starting Websocke server in daemon mode...');
        } else {
            $this->info('Starting Websocke server in interactive mode...');
        }

        $server = new swoole_websocket_server('0.0.0.0', 9501);
        $server->set([
            'daemonize' => $daemonize,
            'log_file' => '/var/log/websocket.log'
        ]);

        $server->on('close', function ($server, $fd) {
            $this->info('close websocket server');
        });

        $server->on('open', function (swoole_websocket_server $server, $request) {
            $this->info('websocket open');
        });

        $server->on('open', [$this, 'onOpen']);
        $server->on('close', [$this, 'onClose']);
        $server->on('message', [$this, 'onMessage']);
        $server->on('request', [$this, 'onRequest']);

        $this->server = $server;
        $this->server->start();
    }

    public function onOpen(swoole_websocket_server $server, $request) 
    {
            $this->info('websocket open');
    }

    public function onClose($server, $fd) 
    {
            $this->info('close websocket server');
    }

    public function onMessage(swoole_websocket_server $server, $frame) 
    {
        $this->info($frame->data);
        $data = json_decode($frame->data, true);

        //对data进行逻辑处理
        $reply = '发送的信息是:' . $data['message'];
        $response = [
            'status' => true,
            'data' => $reply
        ];
        $server->push($frame->fd, json_encode($response));
    }

    //websocket客户端同样支持http协议
    public function onRequest(swoole_http_request $request, swoole_http_response $response) 
    {
        if ($request->post['type'] == self::TYPE_ADMIN) {
            $ret = json_encode($this->commandHandle($request->post['content']));
            return $response->end($ret);
        }
    }

    //操作命名
    public function commandHandle($command) {
        if ($command == 'status') {
            $this->info('handle status');
            return $this->server->stats();
        }
        if ($command == 'restart') {
            $this->info('handle restart');
            return $this->server->reload();
        }
        if ($command == 'stop') {
            $this->info('handle stop');
            return $this->server->stop() && $this->server->shutdown();
        }
        return 'Unknown Command';
    }

    //发送http请求
    public function sendAdminRequest($content) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:9501");
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Expect:']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, [
            'type' => self::TYPE_ADMIN,
            'content' => $content
        ]);

        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }

}

客户端内容

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>websocket client</title>
    </head>
    <body>
        <div>
            <input id="message-content" type="text" name="message" />
            <button onclick="sendMessage()">发送消息</button>
        </div>
    </body>
    <script>
        var wsServer = 'ws://115.159.81.46:9501';
        var websocket = new WebSocket(wsServer);
        websocket.onopen = function (evt) {
            console.log("Connected to WebSocket server.");
        };

        websocket.onclose = function (evt) {
            console.log("Disconnected");
        };

        websocket.onmessage = function (evt) {
            console.log('从服务器接收到json信息: ' + evt.data);
            alert('服务器返回信息:' + JSON.parse(evt.data).data);
        };

        websocket.onerror = function (evt, e) {
            console.log('Error occured: ' + evt.data);
        };

        function sendMessage(){
            var content = document.getElementById('message-content').value;
            var data = {
                message : content,
            }
            websocket.send(JSON.stringify(data));
        };
    </script>
</html>

启动websocket服务器

进入系统根目录,
php artisan websocket [–daemon] //是或不是选择daemon方式
php artisan websocket start|stop|status|restart //默认是start

Upgrade: WebSocket

Connection: Upgrade

Host:http://www.cnodejs.org:8088

Origin:http://www.cnodejs.com

服务端会发回如下:

HTTP/1.1 101 Web Socket Protocol Handshake

Upgrade: WebSocket

Connection: Upgrade

WebSocket-Origin:http://www.cnodejs.org

WebSocket-Location: ws://www.cnodejs.org:8088/echo

切切实实的ws协议,能够参照:http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76

我们在开发进度中不需求考虑协议的底细,因为websocket
API已经帮我们封装好了。

必要留意的是颇具的通信数据都以以”\x00″开头以”\xFF”结尾的,并且都以UTF-8编码的。

其一进度看似于http的树立连接进程,不一样的是,建立连接之后,接下去客户端和服务端的其余交互都亟需再有其一动作。客户端通过websocket
API提供的如下伍个事件展开编制程序:

onopen 建立连接后触发

onmessage 收到新闻后触发

onerror 发生错误时接触

onclose 关闭连接时接触

让大家全面掌握一下websocket API,他实在非凡不难,上边是独具的API:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23[Constructor(in DOMString url, in optional DOMString protocols)]

[Constructor(in DOMString url, in optional DOMString[] protocols)]

interface WebSocket {

readonly attribute DOMString url;

// ready state

const unsigned short CONNECTING = 0;

const unsigned short OPEN = 1;

const unsigned short CLOSING = 2;

const unsigned short CLOSED = 3;

readonly attribute unsigned short readyState;

readonly attribute unsigned long bufferedAmount;

// networking

attribute Function onopen;

attribute Function onmessage;

attribute Function onerror;

attribute Function onclose;

readonly attribute DOMString protocol;

void send(in DOMString data);

void close();

};

WebSocket implements EventTarget;

详尽的websocket
API,可以参考此文:http://dev.w3.org/html5/websockets/

node.js与websocket的结合

毕竟讲到了正题了,node.js如何与websocket结合,websocket
API是依据事件的,他是对此客户端而言,而对于服务端来说,怎样来处理呢?其实可以大概的明白为促成websocket协议的socket
server开发。

node.js天生便是二个飞快的服务端语言,能够直接使用
javascript直接来处理来自客户端的伸手,这样只要服务端那边需求大量的事情逻辑开发,则可以直接动用node开发。通过node和
websocket的结合能够支付出众多实时性须求很高的web应用,如游戏、直播、股票、监察和控制、IM等等。

而node.js怎么样贯彻websocket的支撑,已经有三个相比成熟的开源系统node-websocket-server:https://github.com/miksago/node-websocket-server,让我们来研讨一二:

实质上原理也是相当粗略正是用node完结了websocket
draft-76的商谈,同时他对外提供了api,能够便宜别的应用程序简化编制程序。

它三番陆回了node的http.Server的风浪和艺术,那样它简化了服务端的编程,同时能够拍卖http的呼吁。

为了落到实处三番五次之间的通讯和音讯的播报,它达成了1个manager类,给每3个连连创立贰个id,然后在内部存款和储蓄器中爱戴3个总是链表,并提供了上线和底线的机关管理。

它还提供对以下多少个事件的接口:

listening 当服务器准备好接受客户端请求时

request 当贰个http 请求发生时接触

stream

close

clientError

error

让大家看看1个node-websocket-server提供的3个server的例证:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27var sys = require(“sys”)

, ws = require(‘../lib/ws/server’);

var server = ws.createServer({debug: true});

// Handle WebSocket Requests

server.addListener(“connection”, function(conn){

conn.send(“Connection: “+conn.id);

conn.addListener(“message”, function(message){

conn.broadcast(“<“+conn.id+”> “+message);

if(message == “error”){

conn.emit(“error”, “test”);

}

});

});

server.addListener(“error”, function(){

console.log(Array.prototype.join.call(arguments, “, “));

});

server.addListener(“disconnected”, function(conn){

server.broadcast(“<“+conn.id+”> disconnected”);

});

server.listen(8000);

以此事例十分的简练,能够看看对于websocket的server端开发,我们已经不要求考虑
websocket磋商的贯彻,他大约拥有和客户端浏览器上websocket
API一样的轩然大波,唯有对连接、断开连接、音信、错误等事件进展处理,那样应用的付出就老大的利落了。

实例:用websocket和node.js搭建实时监督检查系统

由此websocket打通了浏览器和服务端之后,大家就能够品尝搭建一个实际的应用,那里以实时监察系统为例。

直白与linux自己监督工具的整合,将监督检查结果通过websocket直接更到网页上,由于建立了socket长连接,绑定iostat的正式输
出的风波,做到了确实的实时。同时能够支撑对监督结果的议论,增添了二个简短的chat,基于事件的通信中,chat和监察同时发送完全不受影响,所以还可以把越来越多的风云参加进来。

让大家来看望这些进程:

先是是用node.js捕获iostat的输出:

1

2

3

4

5

6var sys = require(“sys”)

, ws = require(‘../lib/ws/server’);

var sys = require(‘sys’);

var spawn = require(‘child_process’).spawn;

var mon = spawn(“iostat”,[“-I”,”5″]);

spawn可以依照参数运行一个进度,同时能够对stdout, stderr, exit
code进行捕获,当那几个事件触发时,能够绑定我们的函数,同时捕获其出口。

此处是iostat的规范输出:

disk0 cpu load average

KB/t tps MB/s us sy id 1m 5m 15m

14.64 4 0.06 7 5 88 0.76 0.95 0.90

大家捕获他的出口,将其发送到客户端去:

1

2

3

4

5mon.stdout.on(‘data’,function(data) {

data = format_string(data);

sys.puts(data);

conn.send(“#mon:”+data+””);

});

客户端也便是浏览器,在吸收消息后,对其开始展览简易的字符串处理,然后就足以从来在网页中输出了。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15w.onmessage = function(e) {

var msg = e.data;

if(msg.match(/#mon:/)) {

var monarr = msg.split(“:”)[1].split(” “);

var body = “”;

for(var item in monarr) {

“+monarr[item]+”

}

$(“#iobody”).html(body);

//log(monarr[0]);

}

else

log(e.data);

}

那边自定义了3个#mon的大致商议,那样能够对越多花色的输出分开处理。

服务端和客户端总共100多行的代码,就曾经完毕了一个实时服务器品质监察和控制种类。

全方位代码下载地址:http://cnodejs.googlecode.com/svn/trunk/monsocket/examples/

(注:本程序仅在mac osx下测试通过)

假若加上奇骏Graph(基于html5),则能够创设越发出彩的实时显示:
 

总结

那篇文章适合node.js的初学者恐怕对于websocket不够理解的人,总计起来,正是以下多少个点:

应用websocket API能够付出web应用实时

websocket api和 node.js能够很周到的匹配

node-websocket-server
封装了websocket协议,使服务端举办websocket的费用,非凡的不难

node的易用性,使其在服务端略加编制程序,即能够创立八个完美的后台服务

node的事件驱动的建制确定保证了系统的一点也不慢,能够利用伊夫ntEmitter定义自身的事件触发

对于命令行输出能够选取spawn来捕获,通过在web应用中丰硕利用linux的各类系统工具

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图