您好,登錄后才能下訂單哦!
一、安裝Nodejs
1下載安裝node.js
下載安裝:地址址http://www.nodejs.cn
使用node.exe來解釋執(zhí)行 寫好的js代碼
環(huán)境變量他會自動配置好
但是你使用第三庫就還要一個環(huán)境變量,指定Node搜索第三方模塊路勁
NODE_PATH是npm安裝好的模塊所在的搜索路勁.
NODE_PATH 值: %AppData%\npm\node_modules;
2.下載安裝cygwin 然后 寫一個hello
找打這個js文件目錄
node js文件名 解釋執(zhí)行即可
二、事件循環(huán)和progress模塊
Node.js事件循環(huán)
1.如果node.js沒有要處理的事件了,那整個就結束.直接退出node
事件里面可以繼續(xù)插入事件,如果有事件是一直要繼續(xù)下去
那node就不會退出,每一次事件處理結束后,等待下一個事件的發(fā)生
一旦有事件發(fā)生就會調用回調函數.回調函數里還可以插入新的事件
2setTimeout插入一個計時器事件,單位為毫秒 觸發(fā)一次結束.
setTimeout(function() { console.log("hello world"); },3000);
3setInterval插入一個不斷循環(huán)的計時器事件.
setInterval(function () { console.log("hello world"); },1000*2);
Progress屬性和事件
1.process模塊用來與當前進程互動,獲取相關操作系統相關信息
2.process是全局模塊 全局變量不需要require
3.process.pid進程pid,version是node版本,platform平臺,
title窗口或進程名稱,argv控制臺啟動傳入的參數,他是個字符串數組
execPath,node所在路勁, env獲得系統的環(huán)境變量
重要方法
cwd 獲取當前工作目錄 uptime獲取進程運行時間,
chdir這只當前的工作目錄 ,
nextTick下一次循環(huán)的時候調用后沒事循環(huán)事件開始前先調用它
4.監(jiān)聽exit事件,node退出會拋出exit事件,當用戶監(jiān)聽這個事件
那么exit事件發(fā)生后會收到通知.
process.on("exit",function(){ console.log("node退出"); });
5.uncaughtException事件function(err){};
6.處理的時候遇到了異常,如果這個異常捕獲,那么就繼續(xù)
處理下一個事件,則否直接停止.
//沒有定義的函數 調用 //解釋器 不會主動捕獲異常,他就不會繼續(xù)執(zhí)行 notfunction();
捕獲異常 這樣node就不會終止運行,
//當有異常發(fā)生 立刻調用這個回調函數 process.on("uncaughtException",function(err){ console.log("捕獲到異常:"+err); });
三、Node.js Net模塊使用TCP通訊
在node.js里所有的net模塊 都是異步的,所以都要通過
綁定事件,來獲取相應的操作是否完成.
server服務器
只要創(chuàng)建一個監(jiān)聽服務器,然后調用監(jiān)聽函數即可
每次有新的連接產生后就調用connection事件
他的參數就是和客戶端通信的socket一個net.Socket實例
這個實例里就要綁定 error錯誤事件,close客戶端關閉事件
還有就是data客戶端發(fā)送數據的事件,這個事件發(fā)送的數據
默認參數data是二進制的,你要調用setEncoding設置編碼
//引入net模塊 var net = require("net"); //創(chuàng)建一個net.Server用來監(jiān)聽 //這個API是創(chuàng)建一個新的TCP或IPC服務。 //當有連接請求 會調用這個匿名回調函數 var server = net.createServer((client_sock)=>{ //收到客戶端接入的回調函數 //client_spcl就是與客戶端通訊的socket console.log("client comming"); }); //指示監(jiān)聽端口 為 connections 啟動一個 server 監(jiān)聽 //server.listen(options[, callback]) //這個函數是異步的,server開始監(jiān)聽,listening事件觸發(fā), //最后一個參數callback就是listening事件監(jiān)聽器. //如果 exclusive 是 false(默認), //則集群的所有進程將使用相同的底層句柄, //允許共享連接處理任務 node事件循環(huán)會一直等待在這 console.log("開始等待客戶端連接"); server.listen({ host: "127.0.0.1", //host: 'localhost', port: 6800, exclusive: true, }); //綁定listening 事件 //當服務被綁定后調用 也就是調用listen函數就調用 server.on("listening",function(){ console.log("start listening ..."); }); //綁定建立鏈接事件 和客戶端不同 //這個會產生一個net.Socket新的實例 //用來和客戶端產生通訊的 上面那個 就是這個參數 //其實就是封裝了這個事件 的回調函數 server.on("connection",function(client_sock){ console.log("新的鏈接建立了"); //綁定 客戶端socket 關閉 事件 client_sock.on("close",function(){ console.log("客戶端關閉連接"); }); //設置 接受數據的編碼 //data默認是二進制格式、 //這個二進制每一個值 對應ASCLL碼的十六進制值 //調用這個底層就將他轉出成utf8的字符串 //然后傳給你 //設置成二進制 //client_sock.setEncoding("hex"); //這樣會把這個Buffer對象轉成二進制字符串給你 client_sock.setEncoding("utf-8"); ////當客戶端給 服務器發(fā)數據的時候 //綁定data事件 當接收到數據時被觸發(fā) //參數data是buffer或者string類型 //數據的編碼由socket.setEncoding()設定 client_sock.on("data",function(data){ console.log("接收到數據",data); }); //監(jiān)聽錯誤事件 通訊可能會出錯 client_sock.on("error",function(e){ console.log("error",e); }); }); //綁定錯誤事件 server.on("error",function(){ console.log("listener err"); }); //綁定關閉事件 server.on("close",function(){ //服務器關閉 如果還有鏈接存在,直到所有連接關閉 //這個事件才會被觸發(fā) console.log("server stop listener"); }); //停止偵聽 連接 // server.unref(); //停止監(jiān)聽 主動關閉socket //參數 就是close事件的回調 可以寫在參數里都可以 //他必須是在停止偵聽之后 調用 //如果不這樣的話 服務器 還是可以收到連接 //server.close();
Client客戶端
首先用ner.creatConnection或者net.connect創(chuàng)建連接到服務器
這時候你就要綁定connect的回調函數,一旦連接成功就會回調
close事件,socket關閉后觸發(fā), data事件,收到數據就觸發(fā)
error事件,當socket有錯誤發(fā)生.
//引入net模塊 var net = require("net"); //鏈接服務器 一旦鏈接成功第二個參數 //就會立刻回調 var c_sock = net.connect({ port:6800, host:"127.0.0.1", },()=>{ console.log("connected to server!"); }); //這里綁定connect事件 和上面那個效果相同 //上面那個是 被封裝成回調函數了 c_sock.on("connect",function(){ console.log("connect success!"); //socket.write(data,[,encoding][,callback]) //在socket上發(fā)送數據,第二個參數指定字符串編碼默認UTF-8 //如果發(fā)數據成功到內核的緩沖返回true,如果全部或部分 //數據在用戶內中排隊,返回false,如果緩沖再次空閑則觸發(fā) //drain事件, 當數據最終寫出之后,調用callback回調. //第二個參數 和 第三個參數是可選的 c_sock.write("hello socket server"); }); //綁定錯誤事件 c_sock.on("error",function(err){ console.log("錯誤"+err); }); //綁定關閉事件 c_sock.on("close",function(){ console.log("關閉socket"); });
四、Node.js二進制數據和Buffer模塊
在網絡數據的傳送過程中,所有的數據都是使用二進制傳送的.
二進制
1.在計算機里存放的數據都是二進制的方式來存儲
2.最小單位為字節(jié),8位二進制-->bit
3.所有數據最終都是二進制的方式存放;
4.比如說你有一個字符串"ABCD" 因為這是幾個英文單詞,但是
無法直接把這個幾個單詞存到電腦里面,因為電腦只認識二進制的
0和1,這時候就要用到編碼,用特定的數字表示特定的符號.
4.ASCLL編碼,'A'-->65數據,把數據當字符,
也就是把字符A轉出一個數據65,然后把65存進去.
5.
Int8/Uint8 一個字節(jié)的整數
Int16/Uint16 二個字節(jié)的整數
Int32/Uint32 4個字節(jié)的整數
Int/Uint 8個字節(jié)整數
Float4個字節(jié)小數, Double 8個字節(jié)的小數;
大尾和小尾
1.兩個字節(jié)0x7766其中 77是高位,66是低位
2.尾指定是地址是低的地方,
3.小尾Lihe指的是低位的數據存在低地址的地方,高位存放在高地址的地方
4.大尾Bigger指的是高位的數據存在低地址的地方,低位存在在高地址的地方
5.計算機中的內存使用的就是小尾. 有的CPU則使用大尾.
6.4個字節(jié)的數據,存到內存的4個字節(jié)
小尾: LE高位的數據-->高地址字節(jié)的地方==高高低低
大尾: BE高位的數據-->地地址字節(jié)的地方==低高低高
Buffer Pool
1.node.js使用Buffer對象來存放二進制數據;
2.為了快速分配,先從Buffer池分配,如果分配不成功,再直接
向系統申請 Buffer pool 只能滿足一定范圍內的大小,
如過你申請的過大,那么他會直接向操作系統申請內存.
3.Buffer pool是為了提高內存分配的效率和利用率.
一些小內存首先會從Buffer pool里分配,分配成功直接返回這個內存
如果分配不成功,再向操作系統去申請,回收的時候直接丟給操作系統.
4.Buffer就為我們提供了,大小不大,但是分配頻繁的內存,
做了一個緩存池,提高運行效率. 減少內存碎片.
5.創(chuàng)建一個Buffer對象 Buffer一旦分配大小,再也無法改變
如果這時候你使用越界,就會出現錯誤.
length屬性獲取Buffer對象的長度.
Buffer.alloc(); Buffer.allocUnsafe();Buffer.allocUnsafeSlow()
Buffer.from(array),Buffer.from(buf),Buffer.from(string)
//(1)分配10個字節(jié) //(2)會給這些內存一個初值,如果你每指定, //那么這個初值就是0 //41十六進制從ASCLL碼的41表示A ////輸出十個 "41" 41是十六進制 var buf = Buffer.alloc(10,'A'); //這樣也可以 代表十六進制 41 //輸出十個 "41" 41是十六進制 buf = Buffer.alloc(10,0x41); //也可以是字符串 buf = Buffer.alloc(10,"Hell"); /////////Unsafe //(1)他會分配一個給定大小的Buffer內存 //(2)不會對這些內存去賦初值的. //這個內存是隨機的數據 buf = Buffer.allocUnsafe(10); /////////UnsafeSlow //沒有從緩沖池里面高效的分配 //直接從操作系統分配,更慢所以叫Slow //Unsafe 是沒有初始化的內存 buf = Buffer.allocUnsafeSlow(10); //獲得Buffer對象的長度 console.log(buf.length); /////////from(string) //更方便的創(chuàng)建方式類似于復制 //分配一個BUffer對象,用來存放字符串的二進制. //輸出結果是每個字母對應的十六進制ASCLL碼 buf = Buffer.from("HelloWorld"); ////////from(array) //輸出的是每個數字十進制,對應的十六進制 buf = Buffer.from([123,456,789,-1,45]); //////from(Buffer) //重新場景一個Buffer把原來buf的數據拷貝給新的 var buf2 = Buffer.from(buf); console.log(buf2); /////讀取其中的一個數據 //輸出的是123 console.log(buf[0]); console.log(buf);
讀寫B(tài)uffer
1.Buffer讀取字節(jié)buf[index]使用下標
這個索引是 0 到 length - 1,才是合法范圍.
2.根據大大尾小尾來決定使用BE大尾/LE小尾
3.readFloatBE/readDoubleBE/readFloatLE/readDoubleLE
4.讀/寫整數:read/write
Int8/Uint 一個字節(jié)不存在大尾小尾.
Int16BE/Int16LE/UInt16BE/UInt16LE
Int32BE/Int32LE/UInt32BE/UInt32LE
IntBE/IntLE/UIntBE/UIntLE
floatBE/floatLE/doubleBE/doubleLE
寫一個整數到Buffer里面
//寫入4個字節(jié) 大尾 //value值,offset是從哪開始寫 //noAssert是否檢查長度是不是有效范圍, //用來檢測內存越界,默認不用檢測,提升性能. //writeInt32LE(value,offset,[.noAssert]) buf.writeInt32BE(65535,0); //用十六進制表示 0x0000ffff //這里輸出的就是00 00 FF FF //因為他是大尾法寫入,他的高位0000 低位FFFF //大端法 大尾把高位放低地址作為起始地址 //所以輸出的就是 00 00 FF FF console.log(buf);
讀取
//使用大尾讀出來 參數是從哪里開始讀 var value = buf.readInt32BE(0); console.log(value);
Buffer重要方法
1.Buffer.byteLength(str,encoding)返回字符對象
str可以說string,Buffer,Array,ArrayBuffer
對應的二進制長度.encoding如果是字符串,字符編碼模式utf-8
也就是存下str需要多長字節(jié).
var len = Buffer.byteLength("HelloWorld"); //輸出10 console.log(len); 也可以是Buffer對象 var len = Buffer.byteLength(buf2); //輸出5 console.log(buf2);
2.交換swap16,swap32,swap64 大尾小尾數據變化
16是兩個字節(jié)交換位置, 32是4個字節(jié)兩個兩個交換位置
64是前面4個和后面4個字節(jié) 交換位置
將buf解析為一個整數數組,并且以字節(jié)順序原地進行交換
//16個字節(jié) var bufer = Buffer.alloc(4*4); bufer.writeInt32LE(65535,0); bufer.writeInt32LE(65535,4); bufer.writeInt32LE(65535,8); bufer.writeInt32LE(65535,12); //輸出ffff0000 4個 //并且是小尾 存放 console.log(bufer);
然后轉換成大尾
bufer.swap32(); //這里輸出的就是0000 ffff 4個 //就是轉換成大端法,高位放地地址. console.log(bufer);
3.buffer.values() 遍歷buf每個字節(jié)
for(var vlu of bufer.values()) { console.log(vlu); }
4.Buffer轉字符串 buf.toString()
比如說二進制字符串
//參數 是編碼 hex是二進制 console.log(bufer.toString('hex'));
5.Buffer轉Json字符串,
JSON.stringify(buf) buffer.toJSON
console.log(bufer.toJSON());
6.Buffer.fill 填充參數可以是字符 字符串 ×××
那這個buffer里所有數據都變成這個了
bufer.fill(23);
bufer.fill("ab")
如果未指定 offset
和 end
,則填充整個 buf
。
這個簡化使得一個 Buffer
的創(chuàng)建與填充可以在一行內完成
例如填充ASCLL碼 'A'
bufer.fill('A');
console.log(bufer);
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。