WebSocket的简单介绍及应用(2)

var socket = new WebSocket("ws://localhost:8080/guest"); socket.onopen = function(openEvent) { console.log("WebSocket conntected."); }; socket.onmessage = function(messageEvent) { var data = messageEvent.data, dataObject = JSON.parse(data); console.log("Guest at " + dataObject.time + ": " + dataObject.guest); }; socket.onerror = function(errorEvent) { console.log("WebSocket error: ", errorEvent); }; socket.onclose = function(closeEvent) { console.log("WebSocket closed."); };

WebSocket的URL格式是ws://与wss://。因此,需要注意下URL地址的写法,这也包括注意WebSocket服务器端的路径(如这里的/guest)等信息。因为是本地的示例所以这里是localhost。

客户端代码的流程很简单:创建WebSocket对象,然后指定onopen、onmessage等事件的回调即可。其中onmessage是客户端与服务器端通过WebSocket通信的关键事件,想要在收到服务器通知后做点什么,写在onmessage事件的回调函数里就好了。

效果及分析

通过node server(假定服务器端的文件名为server.js)启动WebSocket服务器后,用浏览器打开一个引入了前面客户端代码的html(直接文件路径file:///就可以),就可以得到像这样的结果:

WebSocket的简单介绍及应用

联系前面客户端的代码可以想到,实际从创建WebSocket对象的语句开始,连接请求就会发送,并很快建立起WebSocket连接(不出错误的话),此后就可以收到来自服务器端的通知。如果此时客户端还想再告诉服务器点什么,这样做:

socket.send("Hello, server!");

服务器就可以收到:

WebSocket的简单介绍及应用

当然,这也是因为前面服务器端的代码内同样设置了message事件的回调。在这个客户端和服务器都是javascript的例子中,无论是服务器端还是客户端,都用send()发送信息,都通过message事件设置回调,形式上可以说非常一致。

其他可用的数据类型

WebSocket的send()可以发送的消息,除了前面用的字符串类型之外,还有两种可用,它们是Blob和。

它们都代表二进制数据,可用于原始文件数据的发送。比如,这是一个发送Blob类型数据以完成向服务器上传图片的例子:

var fileEl = document.getElementById("image_upload"); var file = fileEl.files[0]; socket.send(file);

然后服务器端可以这样把文件保存下来:

var fs = require("fs"); wss.on("connection", function(ws) { ws.on("message", function(message) { fs.writeFile("upload.png", message, "binary", function(error) { if (!error) { console.log("File saved."); } }); }); });

在客户端接收二进制数据时,需注意WebSocket对象有一个属性binaryType,初始值为"blob"。因此,如果接收的二进制数据是ArrayBuffer,应在接收之前这样做:

socket.binaryType = "arraybuffer";

其他WebSocket服务器端

其他语言来做WebSocket服务器是怎样的呢?下面是一个php的WebSocket服务器的例子(使用Ratchet):

<?php use Ratchet\ConnectionInterface; use Ratchet\MessageComponentInterface; require __DIR__ . '/vendor/autoload.php'; class GuestServer implements MessageComponentInterface { public function onOpen(ConnectionInterface $conn) { $conn->send('The server is listening to you now.'); } public function onMessage(ConnectionInterface $conn, $msg) { $conn->send($this->generateGuestInfo()); } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { $conn->close(); } private function generateGuestInfo() { $jsonString = file_get_contents('http://uinames.com/api?region=china'); $jsonObject = json_decode($jsonString, true); $guest = $jsonObject['name'] . $jsonObject['surname']; $guestInfo = array( 'guest' => $guest, 'time' => date('H:i:s', time()), ); return json_encode($guestInfo); } } $app = new Ratchet\App('localhost', 8080); $app->route('/guest', new GuestServer(), array('*')); $app->run(); ?>

这个例子也同样是由服务器返回{guest: "人名", time: "15:26:01"}的json数据,不过由于php不像Node那样可以用setTimeout()很容易地实现异步定时任务,这里改为在客户端发送一次任意信息后,再去uinames取得信息并返回。

也可以看到,php搭建的WebSocket服务器仍然是近似的,主要通过WebSocket的open、message等事件来实现功能。

在Chrome开发工具中查看WebSocket数据帧

Chrome开发工具中选择Network,然后找到WebSocket的那个请求,里面可以选择Frames。在Frames里看到的,就是WebSocket的数据帧了:

WebSocket的简单介绍及应用

可以看到很像聊天记录,其中用浅绿色标注的是由客户端发送给服务器的部分。

结语

总的来说,把服务器和客户端拉到了一个聊天窗口来办事,这确实是很棒的想法。

即使只从形式上说,WebSocket的事件回调感觉也比定时任务用起来要更亲切一些。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/664c585945e1b9f0c1401f8568bb64ae.html