html5 websocket ping,Html5 websocket浅析

初次接触websocket,究竟它与http协议有何不同,

HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。

这样说,如果我想服务器定时推送消息,比如说天气预报,每隔一段时间就会变化,如何在客户端获取最新信息。

之前是使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

缺点:轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

websocket最大的特点:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息。

数据格式比较轻量,性能开销小,通信高效。

可以发送文本,也可以发送二进制数据。

没有同源限制,客户端可以与任意服务器通信。

废话不多讲,直接上代码:

var ws = new WebSocket("[wss://echo.websocket.org](wss://echo.websocket.org/)");

ws.onopen = function(evt) {

console.log("Connection open ...");

ws.send("Hello WebSockets!");

};

ws.onmessage = function(evt) {

console.log( "Received Message: " + evt.data);

ws.close();

};

ws.onclose = function(evt) {

console.log("Connection closed.");

};

下面我们来分析会怎么输出:

1.onopen建立连接后输出connection open。

2.send发送一条消息,在onmessage事件里监听,evt.data输出 hello websockets。

3.close关闭连接,最后输出connection closed。

websocket状态

webSocket.readyState

CONNECTING:值为0,表示正在连接。

OPEN:值为1,表示连接成功,可以通信了。

CLOSING:值为2,表示连接正在关闭。

CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

我们可以在这些特殊时刻做许多事情

switch (ws.readyState) {

case WebSocket.CONNECTING:

// do something

break;

case WebSocket.OPEN:

// do something

break;

case WebSocket.CLOSING:

// do something

break;

case WebSocket.CLOSED:

// do something

break;

default:

// this never happens

break;

}

我们可以给每个事件添加多个函数:

ws.addEventListener('open', function (event) {

console.log('socket open')

});

ws.addEventListener('open', function (event) {

ws.send('Hello Server!');

});

代码示例

这样吧,我们下面给出一段示例代码,更能说明问题。

1.下面是一个点击切换的事件,控制socket的链接与释放。

function ToggleConnectionClicked() {

if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {

ws.close();

} else {

Log("准备连接到聊天服务器 ...");

try {

ws =

new WebSocket("ws://" + document.getElementById("Connection").value);

SocketCreated = true;

} catch (ex) {

Log(ex, "ERROR");

return;

}

document.getElementById("ToggleConnection").innerHTML = "断开";

ws.onopen = WSonOpen;

ws.onmessage = WSonMessage;

ws.onclose = WSonClose;

ws.onerror = WSonError;

}

};

2.各种事件函数。

function WSonOpen() {

Log("连接已经建立。", "OK");

$("#SendDataContainer").show("slow"); //消息发送窗口显示

};

function WSonMessage(event) {

Log(event.data);

};

function WSonClose() {

Log("连接关闭。", "ERROR");

document.getElementById("ToggleConnection").innerHTML = "连接";

$("#SendDataContainer").hide("slow");

};

function WSonError() {

Log("WebSocket错误。", "ERROR");

};

3.当用户按下发送按钮,客户端会调用WebSocket对象向服务器发送信息,并且这个消息会广播给所有的用户

function SendDataClicked()

{

if (document.getElementById("DataToSend").value != "") {

ws.send(document.getElementById("txtName").value + "说 :\"" +

document.getElementById("DataToSend").value + "\"");

document.getElementById("DataToSend").value = "";

}

};

数据类型

注意,服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)。

ws.onmessage = function(event){

if(typeof event.data === String) {

console.log("Received data string");

}

if(event.data instanceof ArrayBuffer){

var buffer = event.data;

console.log("Received arraybuffer");

}

}

除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型。

// 收到的是 blob 数据

ws.binaryType = "blob";

ws.onmessage = function(e) {

console.log(e.data.size);

};

// 收到的是 ArrayBuffer 数据

ws.binaryType = "arraybuffer";

ws.onmessage = function(e) {

console.log(e.data.byteLength);

};

可能有同学对blob和arraybuffer(二进制数组)不是很了解,这里我简单讲一下arraybuffer的用法。

ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写,视图的作用是以指定格式解读二进制数据。

var buf = new ArrayBuffer(32);

上面代码生成了一段32字节的内存区域,每个字节的值默认都是0。可以看到,ArrayBuffer构造函数的参数是所需要的内存大小(单位字节)。

为了读写这段内容,需要为它指定视图。DataView视图的创建,需要提供ArrayBuffer对象实例作为参数。

var buf = new ArrayBuffer(32);

var dataView = new DataView(buf);

dataView.getUint8(0) // 0

上面代码对一段32字节的内存,建立DataView视图,然后以不带符号的8位整数格式,读取第一个元素,结果得到0,因为原始内存的ArrayBuffer对象,默认所有位都是0。

ArrayBuffer有一个静态方法isView,返回一个布尔值,表示参数是否为ArrayBuffer的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或DataView实例。

var buffer = new ArrayBuffer(8);

ArrayBuffer.isView(buffer) // false

var v = new Int32Array(buffer);

ArrayBuffer.isView(v) // true

大家对这段感兴趣的话,可以点 这里.

下面展示了几种数据的发送:

// Sending String

connection.send('your message');

// Sending canvas ImageData as ArrayBuffer

var img = canvas_context.getImageData(100, 100, 400, 320);

var binary = new Uint8Array(img.data.length);

for (var i = 0; i < img.data.length; i++) {

binary[i] = img.data[i];

}

connection.send(binary.buffer);

// Sending file as Blob

var file = document.querySelector('input[type="file"]').files[0];

connection.send(file);

我们可以截取canvas绘画的图像某一部分,通过二进制数组发送给服务器。

var canvas = document.getElementById('canvas');

var ctx = canvas.getContext('2d');

ctx.rect(10, 10, 100, 100);

ctx.fill();

console.log(ctx.getImageData(50, 50, 100, 100));

// ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }

下面分享几个小tip:

1.How to get the IP address of the client?

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws, req) {

const ip = req.connection.remoteAddress;

});

获取远程客户端ip。

2.How to detect and close broken connections?

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

function heartbeat() {

this.isAlive = true;

}

wss.on('connection', function connection(ws) {

ws.isAlive = true;

ws.on('pong', heartbeat);

});

const interval = setInterval(function ping() {

wss.clients.forEach(function each(ws) {

if (ws.isAlive === false) return ws.terminate();

ws.isAlive = false; // 断开

ws.ping('', false, true); //重新ping 如果可以ping通,会接受pong

});

}, 30000);

上面这个例子检测了与服务器通信的客户端,若是有链接异常的会被terminate。

3.How to send broadcast to all connected client

const server = http.createServer(app);

const wss = new WebSocket.Server({ server });

wss.on('connection', function connection(ws) {

ws.on('message', function(message) {

wss.broadcast(message);

}

}

wss.broadcast = function broadcast(msg) {

console.log(msg);

wss.clients.forEach(function each(client) {

client.send(msg); //这个有所疑问 为什么是send 这个时候不该是receive吗

});

};

server.listen(8080, function listening() {

console.log('Listening on %d', server.address().port);

});

上面是服务器接收了一个信息后,将该信息发送给所有与之建立连接的client。或许下面这个更适合。

var ws = require("ws");

global_counter = 0;

all_active_connections = {};

ws.createServer(function (websocket)

{

websocket.on('connect', function()

{

var id = global_counter++;

all_active_connections[id] = websocket;

websocket.id = id;

}).on('message', function (data) {

if (data == 'broadcast me!')

{

for (conn in all_active_connections)

all_active_connections[conn].write(data); // 这里用的write

}

}

}).on('close', function() {

delete all_active_connections[websocket.id];

});

}).listen(8080);

今天关于websocket的知识就讲解到这里,其实有很多资源可以去学习,socket.io也是一个很好的学习途径,如果有空我会做一期node.js配合socket的文章。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值