SSE && WebSockets

参考

http://www.bitscn.com/school/HTMLCSS/201402/194940.html

WebSockets 定义了一个全双工的通信信道,只需Web上的一个 Socket即可进行通信,能减少不必要的网络流量并降低网络延迟。

大部分是围绕轮询和其他服务器端推送技术展开的,其中最著名的是Comet。Comet技术可以让服务器主动以异步方式向客户端推送数据。

Comet

Comet是服务器端的推送,实现Comet有两种方式, 长轮询和流。

  • 长轮询

    长轮询是短轮询的一个翻版, 短轮询是浏览器定时向服务端发送请求看看有没有数据更新。长轮询则是浏览器发送了一个请求之后, 服务端一直保持连接打开状态,直到有数据可以相应,发送完数据后关闭连接。之后浏览器再发起请求。

  • Http流

    流不同于轮询 流在页面整个生命周期只内只有一个连接, 浏览器向服务器发送请求, 而服务器保持连接打开, 然后周期性的向浏览器发送数据。

SSE 服务器发送事件

参考

http://www.cnblogs.com/wintersun/p/3735160.html

http://www.cnblogs.com/goody9807/p/4257192.html

http://www.w3school.com.cn/html5/html_5_serversentevents.asp

简单说,所谓SSE,就是浏览器向服务器发送一个HTTP请求,然后服务器不断单向地向浏览器推送“信息”(message)。这种信息在格式上很简单,就是“信息”加上前缀“data: ”,然后以“\n\n”结尾。

(对于多行数据 只有最后一行是\n\n 其他是\n)

比如这样

$ curl http://example.com/dates
data: 1394572346452
data: 1394572347457
data: 1394572348463

SSE对象有三个事件:open、error和message

SSE是单向通道, 只能服务端向浏览器发送数据

使用SSE, 浏览器不用频繁的发送请求, 实际上在Network中就看不到请求却可以得到服务端的数据

var source = new EventSource('sse.php');

source.onmessage = function(e){
console.log(e.data);
};

服务端

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true){
echo "data: start\n";
echo "data:".date("Y-m-d H:i:s")."\n\n";
// @ob_flush();
// @flush();
ob_flush();
flush();
sleep(1);
}
?>

PS SSE有跨域限制

接下来用NodeJS 来实现SSE

之前提到了SSE不能跨域, 因此我们的这个NodeJS服务器不仅仅要完成SSE的处理, 还要有完成页面的请求

http://www.cnblogs.com/wintersun/p/3735160.html

var http = require("http"), fs = require("fs");
var port = parseInt( process.argv[2] || 1234 );
http.createServer(function(request, response){
console.log("Client connected:" + request.url);
if(request.url!="/sse"){
fs.readFile("sseNode.html", function(err,file){
response.writeHead(200, { 'Content-Type': 'text/html' });
var s = file.toString(); //file is a buffer
s = s.replace("basic_sse.php","sse");
response.end(s);
});
return;
}
//Below is to handle SSE request. It never returns.
response.writeHead(200, { "Content-Type": "text/event-stream" });
var timer = setInterval(function(){
var content = "data:" + new Date().toISOString() + "\n\n";
var b = response.write(content);
if(!b)console.log("Data got queued in memory (content=" + content + ")");
else console.log("Flushed! (content=" + content + ")");
},1000);
request.connection.on("close", function(){
response.end();
clearInterval(timer);
console.log("Client closed connection. Aborting.");
});
}).listen(port);
console.log("Server running at http://localhost:" + port);

WebScockets

为了建立WebSocket通信,客户端和服务器在初始握手时,将HTTP协议升级到WebSocket协议。一旦连接建立成功,就可以在全双工模式下在客户端和服务器之间来回传送WebSocket消息。

ws://和wss://前缀分别表示WebSocket连接和安全的WebSocket连接。

事件 处理程序 说明
open Socket.onopen z此事件发生在套接字建立连接。
message Socket.onmessage 此事件发生时,客户端收到来自服务器的数据。
error Socket.onerror 此事件发生时有任何通信错误。
close Socket.onclose 此事件发生在连接关闭。

需要知道的是socket都是建立在一个HTTP服务的基础上的,因此创建一个socket之前需要创建一个HTTP

一个简单的例子

服务端部分(NodeJS)

来自http://my.oschina.net/fuckboogie/blog/201615

 var http = require('http');
var io = require('socket.io');
var yourserver = http.createServer(function (request, response) {
response.writeHead(250, { 'Content-Type': 'text/html' });
response.end('Your WebSocket server is running');
}).listen(1234);
var yoursocket = io.listen(yourserver);
yoursocket.on('connection', function (client) {
client.on('message', function (data) {
console.log('Client Message: ', data);
var current = new Date().getTime();
client.emit('YourMessageResponse', data + '->' + current);
});
client.on('disconnect', function () {
console.log('Your Client disconnected');
});
});

客户端部分

客户端需要引入socket.io.js 这个文件才有io对象, 这个文件在node_modules的socket.io中 之前我们启动了一个端口是1234的服务器 服务器会自动寻找这个文件

<script src='http://localhost:1234/socket.io/socket.io.js'></script>

    var yoursocket = null;
yoursocket = io.connect('http://localhost:1234');
yoursocket.on('connect', function() {
console.log('You are connected to Server');
yoursocket.send(new Date());
});
yoursocket.on('YourMessageResponse', function(data) {
console.log('Server Response: ' + data + '<br />');
setTimeout(function(){
yoursocket.send(data + new Date());
},1000);
});
yoursocket.on('disconnect', function() {
console.log('You are disconnected from Server<br />');
});

不用socket.io 就用W3C的socket

参考

http://codular.com/node-web-sockets

服务端

var WebSocketServer = require('websocket').server;
var http = require('http'); var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
}); wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
}); function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
} wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.sendUTF('first message from server');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});

客户端(原生的websocket)

    var soc = null;
var websocket = new WebSocket('ws://localhost:8080','echo-protocol');
websocket.onopen = function(e){
console.log(e);
// setInterval(function(){
// websocket.send('hehe')
// }, 1000);
}
websocket.onmessage = function(e){
console.log(e);
setTimeout(function(){
websocket.send('client');
},1000)
}

SSE && WebSockets的更多相关文章

  1. ActionCable的部署(参考Gorails)

    Gorails视频 https://gorails.com/deploy/actioncable Action Cable – Integrated WebSockets for Rails http ...

  2. Long-Polling, Websockets, SSE(Server-Sent Event), WebRTC 之间的区别

    在下面的示例中,客户端指的是浏览器,服务器指的是网站服务器主机. 为了更好的理解这些知识点,你应该简单了解典型的http网站是如何工作的. 普通的http: 客户端从服务器端请求网页 服务器作出相应的 ...

  3. How Javascript works (Javascript工作原理) (五) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势

    个人总结: 1.长连接机制——分清Websocket,http2,SSE: 1)HTTP/2 引进了 Server Push 技术用来让服务器主动向客户端缓存发送数据.然而,它并不允许直接向客户端程序 ...

  4. Long-Polling, Websockets, SSE(Server-Sent Event), WebRTC 之间的区别与使用

    1.首先看下最简单的SSE: 只用支持SSE的浏览器(大部分)即可,浏览器内置EventSource对象,该对象默认隔三秒刷新一下response的数据. HTML代码(取自w3cschool): & ...

  5. Long-Polling, Websockets, SSE(Server-Sent Event) 之间有什么区别?

    链接:http://www.mamicode.com/info-detail-1327667.html https://www.jianshu.com/p/d3f66b1eb748?from=time ...

  6. HTML5的Server-Sent Events (SSE)

    HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端.(通常叫数据推送).我们来看下,传统的WEB应用程序通信时的简单时序图: 现在Web App中,大都有A ...

  7. JavaScript是如何工作: 深入探索WebSocket和HTTP/2与SSE + 如何选择正确的路径!

    原文:<JavaScript是如何工作: 深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 文章底部分 ...

  8. WebSocket & websockets

    WebSocket & websockets https://en.wikipedia.org/wiki/WebSocket https://developer.mozilla.org/en- ...

  9. SSE指令集学习:Compiler Intrinsic

    大多数的函数是在库中,Intrinsic Function却内嵌在编译器中(built in to the compiler). 1. Intrinsic Function Intrinsic Fun ...

随机推荐

  1. SqlServer2008 数据库同步的两种方式 (发布、订阅)

    尊重原著作:本文转载自http://www.cnblogs.com/tyb1222/archive/2011/05/31/2064944.html 上篇中说了通过SQL JOB的方式对数据库的同步,这 ...

  2. provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接

    问题描述: SQL Sever2012 中:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为 ...

  3. 最近做OpenWrt的总结

    用到了哪些东西 需要在OpenWrt上开发一个客户端,用C语言写还比较方便,最开始在linux上跑,后面移植到路由器上,做成ipk.除了稍微修改了下Makefile,其他的什么都没改. 因为需要做个配 ...

  4. Windows系统环境下一个Apache运行多个PHP版本

    我个人机器上环境是基于Apache2.2运行的PHP5.2/4,如你想部署其他版本的PHP或在更多的版本之间切换,同理操作步骤是一致的. 依本人环境为例,机器上已经安装了PHP5.2版本, 所以首先重 ...

  5. PHP MySql数据库访问

    PHP MySql数据库访问 计应134   凌豪 1.MySql数据库的连接 要操作MySql数据库,首先必须与MySQl数据库建立连接,连接MySQL服务器的语句如下: <?php$link ...

  6. PostCss 从0开始

    PostCss 摘自 http://ju.outofmemory.cn/entry/215105 http://www.w3cplus.com/PostCSS/postcss-deep-dive-pr ...

  7. J2SE知识点摘记(八)

    1.        多线程指的是在单个进程中可以同时运行多个不同的线程,执行不用的任务.多线程意味着一个程序的多行语句可以看上去几乎同时进行. 同样作为基本的执行单元,线程是划分得比进程更小的执行单位 ...

  8. delphi高手突破学习笔记之面向对象类和对象的本质

    知识点1:堆和栈 每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack). 堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的.例如,用GetMem函数获取了一 ...

  9. _.each的用法2

    有这样一个需求:一个对象数组: 内容如下: {[ {id:"ssss",position:"4"}, {id:"ssss",position ...

  10. python setattr(),getattr()函数

    setattr(object,name,value): 作用:设置object的名称为name(type:string)的属性的属性值为value,属性name可以是已存在属性也可以是新属性. get ...