好吧,四月的第一篇學習筆記,我知道我是偷懶了,<攤手>,一些整理參考《nodejs入門經典》,僅供個人學習。
一 動態web的簡史
從歷史上說,web在設計上並沒有考錄動態,它是圍繞着文檔設計的可以在一個時刻閱讀單一的文檔。用戶從瀏覽器請求一個web頁面,獲得響應,然后瀏覽器顯示頁面——這樣的循環是許多為web提供力量的技術的設計基礎。隨着時間的推移,開發人員更多的想法,不只是顯示文檔,而JavaScript就是推動web頁面功能發展的中心。在20世紀90年代后期,DHTML這個術語出現了,它描述的是使用JavaScript,css和html更改頁面的某些部分的能力,從而讓web頁面更有交互性,也就是動態性。它引入了諸如ticker,顯示頁面的隱藏部分以及簡單的動畫等內容。DHTML原本是個行為術語,它講解的是用戶與web頁面交互的方法以及當交互發生時會發生什么。web標准社區后來采用DOM腳本,以可響應的方式來描述對web頁面的操縱,這樣當瀏覽器的某些插件不可用時,瀏覽器可以優雅的降級。
Ajax是動態web頁面的下一個巨大進步,它和DHTMl一樣,描述了一組包括js,XML,html和css在內的技術。它讓開發人員可以無需刷新web頁面就能從服務器請求數據。這意味着可以在諸如用戶單擊按鈕這樣的特定事件發生的時候,從服務器請求新的數據。由於整個web頁面無需刷新,就帶來了更具有交互性,動態的體驗。
不可否認,在創建動態web頁面上,ajax將繼續發揮極大的作用;但在某些領域,它卻極為不足。如果從服務器請求數據,Ajax可以工作的很好;但如果服務器想將數據推送到瀏覽器呢?Ajax技術無法很容易地將數據推送到客戶端,雖然諸如Comet這樣的一些技術已經讓其成為了可能。使用ajax技術可以實現雙向數據流,但需要跨過許多障礙才行,而且不同的瀏覽器工作方式也不同。
WebSocket 是對在服務器和客戶端之間實現雙向實時通信問題的響應。它的思想是,從頭開始,設計一個開發人員可以使用的標准以便以一致的方式創建應用程序;而不是通過復雜的,並不總能在所有瀏覽器中都正常工作的設置來使用現有技術完成這一任務。WebSocket的基本思想是在web服務器和瀏覽器之間保持連接持久打開。這就使得不管是服務器還是瀏覽器都可以在需要的時候推送數據。由於連接是持久的,所以數據的交換就非常快,也就成就了‘實時’這個術語。WebSocket 不支持諸如重新連接處理(reconnetion handling)或者心跳(heartbeat)這樣的功能,但諸如Socket.IO這樣的庫提供了這些功能,同時還對某些跨瀏覽器的問題做了抽象。
二Socket.IO是什么?
Socket.IO是node.js的一個模塊,它是通過WebSocket進行通信的一種簡單方式。WebSocket協議很復雜,從頭開始斌寫一個支持WebSocket的應用程序將需要花費很多時間。Socket.IO提供服務器和客戶端雙方的組件,所以只需一個模塊就可以給應用程序加入對WebSocket的支持。Socket.IO也解決了各瀏覽器的支持問題(不是所有瀏覽器都支持WebSocket)並讓實時通信可以跨幾乎所有常用的瀏覽器實現。Socket.IO的設計非常好,將實時通信帶入應用程序的過程便得非常簡單。如果想做任何涉及在web服務器和瀏覽器之間通信的事情,那么nodejs和Socket.IO是極好的選擇哦!。
三Socket.IO示例
1.新建一個文件夾,我取名叫mySocket
2.在文件夾中創建一個名為package.json的文件並加入以下內容來聲明依賴模塊,輸入如下內容
{ "name":"socket.io", "version":"0.0.1", "dependencies":{ "socket.io":"0.8.7" } }
3.在文件夾中再創建一個名為app.js的文件,輸入如下內容
var http=require('http');
var fs=require('fs');
var sever=http.createServer(function(req,res){
fs.readFile('./index.html',function(err,data){
res.writeHead(200,{'Content-Type':'text/html'});
res.end(data,'utf-8');
});
}).listen(3000,'127.0.0.1');
console.log('server running at http://127.0.0.1:3000');
var io=require('socket.io').listen(sever);//為了在服務器上加入Socket.IO的功能,必須將Socket.IO庫包括進來,而后附加到服務器上。
io.socket.on('connection',function(socket){//在啟動了服務器的Socket.io之后,用於初始化,需要一些代碼來讓Socket.io對特定事件作出響應,Socket.io偵聽許多事件,這里只是示例
console.log('user conneted');
socket.on('disconnect',function(){
console.log('user disconnet');
});
});
4.在文件夾中,創建一個名為index.html的文件,輸入如下內容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Socket.io</title> </head> <body> <h1>I Am Socket.IO</h1> <script src="https://cdn.bootcss.com/socket.io/1.7.3/socket.io.js"></script> <script> var socket=io.connect('http://127.0.0.1:3000'); </script> </body> </html>
5.在終端運行如下命令安裝依賴模塊:
npm install
6.從終端運行如下命令啟動服務器:
node app.js(注意是在mysocket的文件路徑下運行)
7.打開瀏覽器訪問http://127.0.0.1:3000.
8.可看到顯示‘I Am socket.IO’的頁面。
9.檢查服務器記錄在終端的日志,可以看到‘user connected’。
10.打開另一個瀏覽器,瀏覽http://127.0.0.1:3000
11.可在服務器日志上看到另一條‘ user connected’。
12.關閉瀏覽器。
13.在服務器日志上看到‘user disconnected’。
這個示例僅僅是演示了當客戶端做諸如連接和斷開連接這樣的事情時,socket.io對特定事件的偵聽。
四 從服務器發送數據到客戶端
看以下代碼
io.sockets.on('connection',function(socket){
socket.emit('message',{text:"you have connected"});//向客戶端發送消息
});
注意到這個示例中,Socket.IO發送的是一個JavaScript對象,也可以使用更復雜的數據結構。
這段代碼需要添加到應用程序的服務器端。只要客戶端連接,它就將數據發送給每一個新的客戶端,而如果想給當前所有的客戶端都發送消息,則需要發送廣播消息
io.sockets.on('connection',function(socket){
socket.emit('message',{text:'A new user has connected"});
socket.broadcast.emit('massage',{text:'A new user has connected'});
});
這是相似的,不同的只是消息發送給所有已連接的客戶端而不僅僅是剛剛連接的客戶端。注意broadcast的發送不包括自己。還有一點,示例中,消息以JavaScript對象在‘message’事件下發送。‘message’這個詞可以是任何東西,但它是重要的,因為接收到數據時需要設置客戶端偵聽‘message’事件。不一定必須以JavaScript對象來發送數據,如果需要的話也可以發送文本,但使用JavaScript對象可以讓客戶端更容易使用數據。
接下來需要做的就是客戶端要包含如下js以便首先連接Socket.io服務器然后偵聽在''message’事件上接收的數據,然后做出響應。
var socket=io.connect('http://127.0.0.1:3000'); socket.on('message',function(data){ alert(data.text); });
通過使用這些功能以及客戶端js,就可以創建實時的計數器來計算已啟用Socket.io的服務器上所連接的客戶端數量。其思想是:當服務器啟動后,計數器從0開始。當客戶端連接到服務器時它遞增1.當客戶端斷開連接時,它遞減1.Socket.IO的消息機制可用以實時地隨着客戶端連接與斷開連接將服務器上客戶端的數量信息更新給所有的客戶端。考慮一下,這就是站點訪問者的實時統計數據了!
那么開始動手吧
1 創建一個名為realtime_socket的文件夾
2.在文件夾中,創建一個名為package.json文件,並輸入如下代碼來聲明依賴模塊
{ "name":"realtime_socket", "version":"0.0.1", "private":true, "dependencies":{ "socket.io":"0.8.7" } }
3.在文件夾中,創建一個名為app.js的文件,並輸入如下代碼
var http=require('http'); var fs=require('fs'); var count=0; var server=http.createServer(function(req,res){ fs.readFile('./index.html',function(err,data){ res.writeHead(200,{'Content-Type':'text/html'}); res.end(data,'utf-8'); }); }).listen(3000,'127.0.0.1'); console.log('server running at http://127.0.0.1:3000'); var io=require('socket.io').listen(server); io.sockets.on('connection',function(socket){ count++; console.log('user conneted'+count+'users present'); socket.emit('users',{number:count}); socket.broadcast.emit('users',{number:count}); socket.on('disconnect',function(){ count--; console.log('user disconnected'+count+'users present'); socket.broadcast.emit('users',{number:count}); }); });
4.在文件夾中,創建index.html文件,並輸入如下代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> Realtime Socket.io</title> </head> <body> <h1>Realtime Socket.IO</h1> <h2> how many users are connect?</h2> <p id="count"></p> <script src="http://localhost:3000/socket.io/socket.io.js "/> <script> var socket=io.connect('http://127.0.0.1:3000'); var count =document.getElementById('count'); socket.on('users',function(data){ //偵聽users事件 console.log('Got update from the server'); console.log('there are'+data.number+'users'); count.innerHtml=data.number; }) </script> </body> </html>
5.從終端運行如下命令安裝依賴模塊
npm install
6.從終端運行如下命令啟動服務器
node app.js(注意是在realtime_Socket.IO的文件路徑下)
7.打開瀏覽器瀏覽:http://127.0.0.1:3000。
8.可以看到一個頁面,顯示“Realtime Socket.IO”等等頁面信息
9.打開拎一個瀏覽器訪問:http://127.0.0.1:3000。
10.服務器更新信息,瀏覽器更新信息。
五 進階:將數據廣播給客戶端
實時計數器展示了客戶端數量數據如何實時往外推送給客戶端。但是如果想讓客戶端之間做通信呢?有可能需要添加聊天功能的場合,或者有需要在客戶端之間發送消息的游戲。為了讓客戶端可以互相通信,首先需要從客戶端發送一條消息給服務器然后從服務器將消息推送給客戶端。過程如下:
1客戶端連接到Socket.IO Node.js服務器。
2一個客戶端發送消息給服務器。
3服務器接受此消息
4.服務器將消息廣播給所有其他客戶端。
我們已經在上一個示例中看到,可以從Socket.IO服務器將消息廣播給客戶端:
socket.broadcast.emit('message',{text:' this goes to everyone'});
我們還看到,可以從服務器給單個客戶端發送消息:
socket.emit('message',{text:' this goes to single client'});
從客戶端發送消息給服務器代碼完全相同!與實時計數器示例不同的是,消息是在客戶端原發的,而且來自客戶端的JavaScript。於是,在客戶端上,必須要有能讓用戶添加消息並提交給服務器的方法。一種實現這個功能的方法是創建一個表單然后使用一些JavaScript來捕獲用戶輸入到表單中的內容並將其發送給服務器。
好吧,原理說這么多,開始實干吧
1.創建一個名為Socket.IO node.js的文件夾
2在文件夾中創建一個名為package.json的文件,並輸入如下內容:
{ "name":"socket_nodejs", "version":"0.0.1", "private":true, "dependencies":{ "socket.io":"0.8.7" } }
3.在文件夾中創建一個名為app.js文件,並輸入如下內容:
var http = require('http'); var fs = require('fs'); var server = http.createServer(function(req, res) { fs.readFile('./index.html', function(err, data) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data, 'utf-8'); }); }).listen(3000, '127.0.0.1'); console.log('server running at http://127.0.0.1:3000'); var io = require('socket.io').listen(server); io.sockets.on('connection', function(socket) { socket.on('message', function(data) {//偵聽客戶端的message事件 socket.broadcast.emit('push message', data); }); });
4.在文件夾中創建一個名為index.html的文件,並輸入如下內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> Socket.io Nodejs</title> </head> <body> <h1> Socket.IO Nodejs</h1> <form action="#" id="message_form"> <textarea id="message" cols="30" rows="10"></textarea> <input type="submit" value="Send message"/> </form> <!-- 將jquery和Socket.IO庫包含進來 --> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="http://localhost:3000/socket.io/socket.io.js "/> <script> var socket=io.connect('http://127.0.0.1:3000');//指示瀏覽器連接位於http://127.0.0.1:3000的Socket.IO服務器 var message=document.getElementById('message'); $('#message_form').submit(function(){//將jquery的submit()方法加入偵聽器,等候用戶提交表單 socket.emit('message',{text:message.value});//發送消息給服務器,文本區域的內容作為消息發送 return false;//防止表單在瀏覽器窗口中提交。 }); socket.on('push message',function(data){ //偵聽push message事件 $('form').after('<p>'+data.text+'</p>');//捕捉接收的數據,寫入dom }); </script> </body> </html>
5.在終端輸入:
npm install
6.從終端啟動服務器:
node app.js(在文件夾路徑下)
7.打開瀏覽器瀏覽:http://127.0.0.1:3000
8打開另一個瀏覽器訪問:http://127.0.0.1:3000
9在文本框中輸入內容並單擊submit。
10在另一個瀏覽器中可看到消息出現
擴展:
ajax和socket.io之間有什么區別?
Socket.IO提供的功能比ajax要多得多,比如很容易就能實時地將數據推送給客戶端。如果可以使用WebSocket,那么客戶端和服務器之間的連接就會是持久的。而對於ajax而言,每次都需要重新連接
另外,WebSocket和ajax的服務目標不同,所以不好說使用哪個不使用哪個。ajax適合瀏覽器需要時不時請求數據並且數據有可能需要緩沖的場景。如果經常需要在客戶端之間接收發送數據,而且有很多客戶端,那么應該使用WebSocket。如果要構建一個客戶端能互相通信的聯網應用程序,那么WebSocket是更好的選擇
推送和拉取消息之間有何不同?
推送消息意味着新的消息通過持久連接推送到客戶端。這意味着客戶端無需請求獲得新消息。作為對比,拉取消息意味着客戶端必須檢查服務器上的內容,看看是否有新的消息可用。
WebSocket當前對瀏覽器的支持如何?
訪問http://canuuse.com並輸入WebSocket,就會看到WebSocket的支持情況。在移動設備上,對websocket的支持不是很好於是這就增加了使用Socket.IO的籌碼了。
使用socket.io比起單純使用websock有何優勢?
如果不能使用websocket,socket.io會使用其他傳輸方法,來處理並不完全支持websocket的瀏覽器問題,(Socket.IO會嘗試使用Adobe flash socket,ajax長輪詢,ajax多部分流,forever iframe 或者jsonp輪詢)。這就意味着無需編寫更多的代碼就可以讓應用程序支持更多瀏覽器。
