参考
http://www.bitscn.com/school/HTMLCSS/201402/194940.htmljavascript
WebSockets 定义了一个全双工的通讯信道,只需Web上的一个 Socket便可进行通讯,能减小没必要要的网络流量并下降网络延迟。php
大部分是围绕轮询和其余服务器端推送技术展开的,其中最著名的是Comet。Comet技术可让服务器主动以异步方式向客户端推送数据。html
Comet是服务器端的推送,实现Comet有两种方式, 长轮询和流。html5
长轮询
长轮询是短轮询的一个翻版, 短轮询是浏览器定时向服务端发送请求看看有没有数据更新。长轮询则是浏览器发送了一个请求以后, 服务端一直保持链接打开状态,直到有数据能够相应,发送完数据后关闭链接。以后浏览器再发起请求。java
Http流
流不一样于轮询 流在页面整个生命周期只内只有一个链接, 浏览器向服务器发送请求, 而服务器保持链接打开, 而后周期性的向浏览器发送数据。node
参考
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.aspweb
简单说,所谓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);
为了创建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) }