nodejs:net模塊學習
nodejs:net模塊學習
net模塊是是nodejs的一個核心模塊。而且,http客戶端與http服務端的通信均依賴于socket(net.Socket)。我也來學習一波
net模塊的組成
不難看出,net模塊主要包含兩部分:
- net.Server:TCP server,內部通過socket來實現與客戶端的通信。
- net.Socket:tcp/本地socket的node版實現,它實現了全雙工的stream接口。
簡單例子
netServer.js(服務端):
//導入net模塊
const net =require("net");
//創建server
const server = net.createServer((socket)=>{
socket.write("Hello");
socket.on("data",(data)=>{
//轉換格式,得到的data是buffer類型
console.log(data.toString());
});
socket.on("error",()=>{
console.log("socket對象發生error事件");
});
socket.on("close",()=>{
console.log("socket對象發生close事件");
})
})
//捕獲server對象發生錯誤
server.on("error",()=>{
console.log("server對象發生error事件");
})
//監聽端口
server.listen(8888,()=>{
console.log("socket已成功開啟8888端口");
})
netClient.js(客戶端):
const net =require("net");
//創建連接
let socket = net.createConnection(8888,"192.0.0.10",()=>{
console.log("已經成功連接到服務器了,可以通訊了");
})
socket.on("data",(data)=>{
console.log(data.toString());
socket.write("兔子哪里跑");
})
在代碼對應的目錄下運行服務端和客戶端,結果如下:
服務端:
客戶端:
接下來是net.server和net.socket的其中一些介紹:
服務端 net.Server
server.close(callback])
關閉服務器,停止接收新的客戶端請求。有幾點注意事項:
- 對正在處理中的客戶端請求,服務器會等待它們處理完(或超時),然后再正式關閉。
- 正常關閉的同時,callback 會被執行,同時會觸發 close 事件。
- 異常關閉的同時,callback 也會執行,同時將對應的 error 作為參數傳入。(比如還沒調用 server.listen(port) 之前,就調用了server.close())
結論:
- 已調用server.listen():正常關閉,close事件觸發,然后callback執行,error參數為undefined
- 未調用server.listen():異常關閉,close事件觸發,然后callback執行,error為具體的錯誤信息。(注意,error 事件沒有觸發)
server.ref()/server.unref()
主要用于將server 加入事件循環/從事件循環里面剔除,區別就在于會不會影響進程的退出。
事件 listening/connection/close/error
- listening:調用 server.listen(),正式開始監聽請求的時候觸發。
- connection:當有新的請求進來時觸發,參數為請求相關的 socket。
- close:服務端關閉的時候觸發。
- error:服務出錯的時候觸發,比如監聽了已經被占用的端口。
客戶端 net.Socket
連接相關
- socket.connect():有3種不同的參數,用于不同的場景;
- socket.setTimeout():用來進行連接超時設置。
- socket.setKeepAlive():用來設置長連接。
- socket.destroy()、socket.destroyed:當錯誤發生時,用來銷毀socket,確保這個socket上不會再有其他的IO操作。
數據讀、寫相關
socket.write()、socket.end()、socket.pause()、socket.resume()、socket.setEncoding()、socket.setNoDelay()
數據屬性相關
socket.bufferSize、socket.bytesRead、socket.bytesWritten
事件循環相關
socket.ref()、socket.unref()
緊接著也嘗試做了一個簡單的問答精靈的例子,加深理解:
服務端:
const net =require('net');
const users ={};
const server = net.createServer((socket)=>{
socket.write(`聊天服務支持的指令有:
1、注冊用戶 {"cmd":"addUser","content":"要注冊的用戶名"}
2、發送私信 {"cmd":"privateMessage","toUser":"接收消息的用戶名","content":"消息內容"}
3、群發消息 {"cmd":"all","content":"消息內容"}
`);
let currentUserName;
socket.on("data",(data)=>{
//先把發過來的buffer數據轉成json
try{
JSON.parse(data.toString());
}
catch(e){
socket.write("消息格式錯誤,請重試!");
return;
}
var json = JSON.parse(data.toString());
switch(json.cmd){
case 'addUser':
//判斷該用戶是否重名
for(var key in users){
if(key == json.content){
socket.write('用戶名已被注冊,請重試');
return;
}
}
users[json.content] = socket;
currentUserName = json.content;
socket.write(`恭喜${json.content}用戶注冊成功`);
break;
case 'privateMessage':
//判斷你要聯系的用戶是否存在
for(var key in users){
if(key == json.toUser){
//用戶存在
users[json.toUser].write(`${currentUserName}:${json.content}`);
return;
}
}
socket.write(`用戶${json.toUser}不存在`);
break;
case 'all':
//群發
for(var key in users){
if(key == currentUserName){
continue;
}
users[key].write(`${currentUserName}@所有人:${json.content}`);
}
default:
break;
}
})
});
server.listen(8888,()=>{
console.log('問答精靈服務器已經開啟在8888端口')
})
客戶端:
const net =require("net");
const socket = net.createConnection(8888,"電腦ip地址",()=>{
console.log('已經成功進入問答精靈聊天室');
})
socket.on("data",(data)=>{
console.log(data.toString());
})
process.stdin.resume();
process.stdin.setEncoding("utf8");
process.stdin.on("data",(data)=>{
if(data.toString().startsWith('add:')){
let dataString = data.toString();
//截取空格
let content = dataString.substring(dataString.indexOf(':')+1,dataString.length-2);
data=`{"cmd":"addUser","content":"${content}"}`;
// console.log(data);
}
else if(data.toString().startsWith('@all:')){
let dataString = data.toString();
let content = dataString.substring(dataString.indexOf(':')+1,dataString.length-2);
data=`{"cmd":"all","content":"${content}"}`;
}
else if(data.toString().startsWith('@')){
let dataString = data.toString();
let parts = dataString.split(":");
let to = parts[0].substring(1);
let content = parts[1].substring(0,parts[1].length-2);
data=`{"cmd":"privateMessage","toUser":"${to}","content":"${content}"}`;
}
socket.write(data);
})
結果:
官方文檔
智能推薦
NodeJs 的fs模塊
<1>js 里面的fs模塊 readFile(),readFileSync() writeFile(),writeFileSync() exists(path, callback) mkdir(),writeFile(),readFile() mkdirSync(),writeFileSync(),readFileSync() readdir(),readdirSync() stat(...
nodeJs高階模塊--fs
請問大家: NodeJs只能做的兩件事是什么? 這也能做,那也能做~ just joke~ 實際上,所有后臺語言都能做的兩件事是: 文件操作和網絡編程. 這其實是所有語言的根本。 計算機無外乎就是文件和通信。Linux中,是把一切都當做文件,如果理解了這一點那就無可厚非了. 所以,這里,我想介紹一下NodeJS中一個重要的模塊--fs. 這里我給大家放一個我的框架圖~ (為什么不是http? 懶~...
nodejs發布模塊
nodejs安裝目錄:D:\soft\nodejs 新建js文件:例如:HelloWorld.js--->console.log("hello world!"); 1.創建一個新的模塊 name:wx_ll 2.注冊npm賬號 3.上傳包4.安裝包5.管理包權限6.分析包 7.使用引入包 ...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...