Nodejs環(huán)境實(shí)現(xiàn)socket通信過程解析
結(jié)構(gòu):
socket是應(yīng)用層和傳輸層的橋梁。(傳輸層之上的協(xié)議所涉及的數(shù)據(jù)都是在本機(jī)處理的,并沒進(jìn)入網(wǎng)絡(luò)中)
涉及數(shù)據(jù):
socket所涉及的數(shù)據(jù)是報(bào)文,是明文。
作用:
建立長久鏈接,供網(wǎng)絡(luò)上的兩個(gè)進(jìn)程通信。
nodejs環(huán)境下的簡單通信。
代碼:
serve:
// 1 引入模塊 const net = require('net'); // 2 創(chuàng)建服務(wù)器 let clientArr = []; const server = net.createServer(); // 3 綁定鏈接事件 server.on('connection',(person)=>{ console.log(clientArr.length); // 記錄鏈接的進(jìn)程 person.id = clientArr.length; clientArr.push(person); person.setEncoding('utf8'); // 客戶socket進(jìn)程綁定事件 person.on('data',(chunk)=>{ console.log(chunk); clientArr.forEach((val)=>{ // 數(shù)據(jù)寫入全部客戶進(jìn)程中 val.write(chunk); }) }) person.on('close',(p1)=>{ clientArr[p1.id] = null; } ) person.on('error',(p1)=>{ clientArr[p1.id] = null; }) }) server.listen(800);
client:
// 1 引入模塊 const net = require('net'); const readline = require('readline'); // 2 創(chuàng)建套接字和輸入輸出命令行 let rl = readline.createInterface({ // 調(diào)用std接口 input:process.stdin, output:process.stdout }) let client = new net.Socket(); // 3 鏈接 client.connect(800,'localhost'); client.setEncoding('utf8'); client.on('data',(chunk)=>{ }) client.on('error',(e)=>{ console.log(e.message); }) // 綁定輸io流事件,獲取輸入輸出字符 rl.on('line',(mes)=>{ client.write(mes); })
小結(jié):
server端:綁定連接事件 --> 在連接事件中管理客戶端進(jìn)程對(duì)象(1,把添加到數(shù)組中 2,處理客戶端發(fā)來的數(shù)據(jù))-->開啟端口監(jiān)聽請(qǐng)求 。
client端:創(chuàng)建連接服務(wù)器用的套接字 --> 連接服務(wù)器 。
socket建立的連接是長久連接。而應(yīng)用層的http協(xié)議是3次握手協(xié)議,是短連接。
socket工作原理和http類似,只是不規(guī)定斷開連接的時(shí)間。可以把http理解成一個(gè)人辦一件事情就跑一次連接流程。socket理解成只跑一次連接流程,只到把所有的事情都做完了才回去。
Socket主要作用是實(shí)現(xiàn)客戶端與服務(wù)端的實(shí)時(shí)通信保持通話,它不像ajax請(qǐng)求,每次對(duì)話完成后都會(huì)把連接斷開。Socket通信在
Node.js中實(shí)現(xiàn)其實(shí)很簡單,沒有想象中復(fù)雜,基本上只要懂得監(jiān)聽(.on)和推送(.emit)消息,即能實(shí)現(xiàn)Socket通信。
Socket服務(wù)端
在服務(wù)端使用Socket,需先引入socket.io模塊,該模塊詳細(xì)文檔可參考https://socket.io/:
cnpm install socket.io
服務(wù)端實(shí)例代碼如下:
var server = app.listen(8081, "127.0.0.1", function() { var host = server.address().address; var port = server.address().port; }); /********************socketIO********************/ var io = require('socket.io').listen(server); // 建立連接 io.sockets.on('connection', function(socket) { //此處每個(gè)回調(diào)socket就是一個(gè)獨(dú)立的客戶端,通常會(huì)用一個(gè)公共列表數(shù)組統(tǒng)一管理 // 連接斷開,如關(guān)閉頁面時(shí)觸發(fā) socket.on('disconnect', function() { console.log('已斷開鏈接'); }); // 監(jiān)聽客戶端發(fā)送的消息 socket.on('clientmessage', function(data) { //推送給除自己外其他所有用戶的消息,類似于廣播 socket.broadcast.emit('message', { text: '你的朋友上線了' }); }); //發(fā)送給自己的消息 socket.emit('message', { text: '你上線了' }); });
上例中實(shí)現(xiàn)了4步:
1. 建立連接并添加斷開連接監(jiān)聽。
2. 建立clientmessage監(jiān)聽,當(dāng)客戶端發(fā)來該名稱的事件時(shí),服務(wù)器向除自己外其他的用戶廣播事件名稱為message的消息。
3.在剛建立連接時(shí),向客戶端推送事件名稱為message的消息。
其中主要應(yīng)用到的函數(shù)有5個(gè):
- .on('connection', function(socket){ }):與客戶端建立連接時(shí)監(jiān)聽。
- .on('disconnect', function(){ }):與客戶端斷開連接時(shí)監(jiān)聽。
- .on('event-name', function(data) { }):監(jiān)聽客戶端發(fā)來的消息。
- .broadcast.emit('event-name', { }):向除自己外的所有其他用戶廣播消息。
- .emit('event-name', { }):僅向當(dāng)前連接的客戶端(自己)推送消息。
(注)相關(guān)客戶端的接口關(guān)聯(lián)請(qǐng)往下看客戶端的例子。
Socket客戶端
需先去下載socket.io.js文件,下載地址為:https://github.com/socketio/socket.io-client
客戶端實(shí)例代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>socketio測試</title> <script> var tmp_html = '<link rel="stylesheet" href="../js/libs/bootstrap/3.3.7/css/bootstrap.css" rel="external nofollow" />'; tmp_html += '<script src="../js/libs/jquery/3.2.1/jquery.js"><\/script>'; tmp_html += '<script src="../js/libs/bootstrap/3.3.7/bootstrap.js"><\/script>'; tmp_html += '<script src="../js/libs/socketio/socket.io.js"><\/script>'; document.write(tmp_html); document.close(); </script> </head> <body> <button id="btn">發(fā)送消息</button> </body> <script> var socket = io.connect('http://127.0.0.1:8081'); socket.on('message', function(data) { console.log(data.text); }) $("#btn").click(function() { socket.emit('clientmessage', { text: "hello" }); }); </script> </html>
客戶端主要應(yīng)用到的函數(shù)有2個(gè):
- .on('event-name', function(data) { }):監(jiān)聽服務(wù)端發(fā)來的消息。
- .emit('event-name', { }):向服務(wù)端推送消息。
Socket即時(shí)通信就是那么簡單,而且在連接斷開時(shí)還會(huì)自動(dòng)重連。還有一種實(shí)現(xiàn)方法就是使用net模塊的套接字,可以直接查看Node.js文檔。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
node使用promise替代回調(diào)函數(shù)
這篇文章主要介紹了node使用promise替代回調(diào)函數(shù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05node爬取微博的數(shù)據(jù)的簡單封裝庫nodeweibo使用指南
這篇文章主要介紹了node爬取微博的數(shù)據(jù)的簡單封裝庫nodeweibo使用指南,需要的朋友可以參考下2015-01-01node腳手架搭建服務(wù)器實(shí)現(xiàn)token驗(yàn)證的方法
這篇文章主要介紹了node腳手架搭建服務(wù)器實(shí)現(xiàn)token驗(yàn)證的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01nodejs教程之制作一個(gè)簡單的文章發(fā)布系統(tǒng)
本文主要講述了使用nodejs制作一個(gè)簡單的文章發(fā)布系統(tǒng),使用mongodb數(shù)據(jù)庫,時(shí)間比較緊,功能做的也比較簡單,僅僅是增刪改查,外加附近上傳,有相同需求的小伙伴可以參考下2014-11-11nodejs 使用nodejs-websocket模塊實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)實(shí)時(shí)通訊
這篇文章主要介紹了nodejs 使用nodejs-websocket模塊實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)實(shí)時(shí)通訊的實(shí)例代碼,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11