基于node的tcp客戶端和服務(wù)端的簡(jiǎn)單通信
1.簡(jiǎn)單介紹下TCP/IP
TCP/IP是互聯(lián)網(wǎng)相關(guān)協(xié)議的集合,分為以下四層:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層。
分成四層的好處是,假如只有一層,某個(gè)地方需要改變?cè)O(shè)計(jì)時(shí),就必須把所有整體替換掉,而分層之后只需把變動(dòng)的層替換掉即可。
2. 服務(wù)端編程
node提供了net模塊來(lái)實(shí)現(xiàn)tcp編程。主要分為服務(wù)端編程和客戶端編程兩部分,先來(lái)寫服務(wù)端的:
監(jiān)聽(tīng)客戶端連接
先引入net模塊,再通過(guò)net.createServer 創(chuàng)建一個(gè)TCP服務(wù)器,服務(wù)器可以監(jiān)聽(tīng)一個(gè)connection事件。
net.createServer([options][, connectionListener])
options<Object>allowHalfOpen<boolean> 表明是否允許半開(kāi)的 TCP 連接。默認(rèn)值:false。pauseOnConnect<boolean> 表明是否應(yīng)在傳入連接上暫停套接字。默認(rèn)值:false。
connectionListener<Function> 自動(dòng)設(shè)置為'connection'事件的監(jiān)聽(tīng)器
我們先不傳參數(shù):
var net = require('net');
//創(chuàng)建tcp服務(wù)器
var server = net.createServer();
//監(jiān)聽(tīng)connect事件
server.on('connection', (socket) => {
socket.on('data',(data)=>{
console.log(data.toString(), 'data')
})
})
//設(shè)置監(jiān)聽(tīng)端口
server.listen(8989);
//設(shè)置監(jiān)聽(tīng)時(shí)的回調(diào)函數(shù)
server.on('listening', (res)=>{
console.log('in listen...')
})connection事件當(dāng)有數(shù)據(jù)發(fā)送過(guò)來(lái)時(shí)會(huì)被觸發(fā)。監(jiān)聽(tīng)函數(shù)的參數(shù)是一個(gè)socket,用戶可以使用它與客戶端進(jìn)行交互。
通過(guò)socket的data事件可以打印出發(fā)送過(guò)來(lái)的數(shù)據(jù),在瀏覽器中打開(kāi) http://localhost:8989,瀏覽器會(huì)將請(qǐng)求頭的信息發(fā)送到server,所以輸出結(jié)果如下:

上面代碼中,connection事件可以傳入到createServer中,listen和listening可以合并,寫成下面這種形式:
//第二種寫法
var net = require('net');
//創(chuàng)建tcp服務(wù)器
var server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log(data.toString(), 'data..')
})
});
//設(shè)置監(jiān)聽(tīng)端口
server.listen(8989, (res) => {
console.log('in listen...')
});除了listening和connect事件外,server還有如下事件:
- close:TCP服務(wù)器關(guān)閉的時(shí)候觸發(fā),回調(diào)函數(shù)沒(méi)有參數(shù)
- error:TCP服務(wù)器發(fā)生錯(cuò)誤的時(shí)候觸發(fā),回調(diào)函數(shù)的參數(shù)為error對(duì)象
接收數(shù)據(jù)和發(fā)送數(shù)據(jù)
通過(guò)socket的data事件接收數(shù)據(jù),write方法發(fā)送數(shù)據(jù)
socket.write(data[, encoding][, callback])
//創(chuàng)建一個(gè)TCP服務(wù)器
var server = net.createServer((socket) => {
//'connect'事件的回調(diào)函數(shù)
console.log('客戶端已連接');
socket.on('end', () => {
console.log('客戶端已斷開(kāi)');
})
//接收來(lái)自客戶端的數(shù)據(jù)
socket.on('data', (data) => {
console.log(data.toString(), 'data');
var readSize = socket.bytesRead;
console.log('the size of data is ' + readSize);
})
//向客戶端寫入數(shù)據(jù)
socket.write('hello\r\n');
//設(shè)置連接最大數(shù)量,可不設(shè)
server.maxConnection = 3;
server.getConnections(function (err, count) {
console.log('the count of clieent is ' + count);
});
})
server.listen(8989, () => {
console.log('服務(wù)器已啟動(dòng)');
//獲取地址信息
var address = server.address();
//獲取地址端口
console.log('the port of server is ' + address.port);
console.log('the address of server is ' + address.address);
console.log('the ip family of server is ' + address.family);
})我們先不寫客戶端的代碼,先用telnet工具來(lái)當(dāng)作客戶端來(lái)測(cè)試上面代碼
打開(kāi)命令行工具輸入 telnet localhost 8989


可以看到socket.write('hello\r\n')這句話已經(jīng)生效了,服務(wù)端向客戶端返回了hello,但這樣肯定還不夠,
3. 客戶端編程
客戶端編程比服務(wù)端簡(jiǎn)單,因?yàn)椴挥帽O(jiān)聽(tīng)端口。只要把數(shù)據(jù)從指定的端口發(fā)出去就可以了。
net.createConnection(options[, connectListener]) 用來(lái)創(chuàng)建一個(gè)socket。第一個(gè)參數(shù)必填,要寫發(fā)送的端口號(hào),第二個(gè)參數(shù)是這個(gè)socket的'connect'事件的回調(diào)函數(shù)
//創(chuàng)建一個(gè)客戶端
var client = net.connect({ port: 8989 }, () => {
console.log('連接到服務(wù)器');
//向服務(wù)端發(fā)送數(shù)據(jù)
client.write('hello,i am from client');
})
//監(jiān)聽(tīng)事件,當(dāng)服務(wù)端發(fā)送數(shù)據(jù)過(guò)來(lái)時(shí)會(huì)觸發(fā)該事件
client.on('data', (data) => {
console.log(data, 'data');
client.end()
})
client.on('end', () => {
console.log('已從服務(wù)器斷開(kāi)');
});

上面代碼的client就是一個(gè)socket,所以可以監(jiān)聽(tīng)data事件來(lái)獲取服務(wù)端發(fā)送來(lái)的數(shù)據(jù)。然后socket也可以通過(guò)write來(lái)向服務(wù)端發(fā)送數(shù)據(jù)
4. 一個(gè)小的登錄系統(tǒng)
利用上面的知識(shí),可以實(shí)現(xiàn)一個(gè)小型的登錄系統(tǒng):
/*server.js*/
var net = require('net');
//這兒用一個(gè)對(duì)象來(lái)模擬數(shù)據(jù)庫(kù),保存用戶名和密碼
var user = {
admin: '123',
test: '333',
lucy: '222',
}
//臨時(shí)變量保存用戶輸入的內(nèi)容
var username = '';
var server = net.createServer((socket)=>{
console.log('服務(wù)器已連接');
socket.write('請(qǐng)輸入用戶名:');
socket.on('data',(data)=>{
//通過(guò)stdin輸入的內(nèi)容是buffer,需要轉(zhuǎn)成字符串且清除空格
data = data.toString().trim();
if(!username){
if(user[data]){
socket.write('請(qǐng)輸入密碼:');
username = data;
}else{
socket.write('用戶名不對(duì),請(qǐng)輸入用戶名:');
}
}else {
if(user[username] === data){
socket.write('登錄成功');
}else {
socket.write('密碼不對(duì),請(qǐng)輸入密碼:');
}
}
});
socket.on('close',data=>{
console.log(data);
})
})
server.listen(8899,()=>{
console.log('服務(wù)器監(jiān)聽(tīng)8899端口中')
})

到此這篇關(guān)于基于node的tcp客戶端和服務(wù)端的簡(jiǎn)單通信的文章就介紹到這了,更多相關(guān)基于node的tcp客戶端和服務(wù)端的簡(jiǎn)單通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 基于Node.js和Socket.IO實(shí)現(xiàn)實(shí)時(shí)通信功能
- 淺析如何在Bash中調(diào)用Node運(yùn)行JS文件進(jìn)行數(shù)據(jù)通信
- Node.js中的進(jìn)程間通信
- Node與Python 雙向通信的實(shí)現(xiàn)代碼
- Nodejs環(huán)境實(shí)現(xiàn)socket通信過(guò)程解析
- node實(shí)現(xiàn)socket鏈接與GPRS進(jìn)行通信的方法
- node 利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存
- Node.js進(jìn)行串口通信的實(shí)現(xiàn)示例
相關(guān)文章
node的process以及child_process模塊學(xué)習(xí)筆記
這篇文章主要介紹了node的process以及child_process模塊學(xué)習(xí)筆記,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
手寫簡(jiǎn)版無(wú)三方依賴的Node-Server實(shí)現(xiàn)示例
這篇文章主要為大家介紹了手寫簡(jiǎn)版無(wú)三方依賴的Node-Server實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
nodejs搭建本地服務(wù)器輕松解決跨域問(wèn)題
這篇文章主要介紹了利用nodejs搭建本地服務(wù)器 解決跨域問(wèn)題,需要的朋友可以參考下2018-03-03
在Node.js中實(shí)現(xiàn)文件復(fù)制的方法和實(shí)例
這篇文章主要介紹了在Node.js中實(shí)現(xiàn)文件復(fù)制的方法和實(shí)例,使用FS模塊實(shí)現(xiàn),需要的朋友可以參考下2014-06-06
Node.js API詳解之 repl模塊用法實(shí)例分析
這篇文章主要介紹了Node.js API詳解之 repl模塊用法,結(jié)合實(shí)例形式分析了Node.js API中repl模塊基本功能、函數(shù)、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2020-05-05

