OSI參考模型將網絡通信功能划分為7層,即物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。TCP協議就是位於傳輸層的協議。Node.js在創建一個TCP服務器的時候使用的是net(網絡)模塊。
使用Node.js創建TCP服務器,首先要使用require(‘net’)來加載net模塊,之后使用net模塊的createServer方法就可以創建一個TCP服務器.
net.createServer([options],[connectionListener])
- options是一個對象參數值,有兩個布爾類型的屬性allowHalfOpen和pauseOnConnect,這兩個屬性默認都是false。
- connectionListener是一個當客戶端與服務器端建立鏈接時的回調函數,這個回調函數以socket端口對象作為參數
下面代碼構建一個TCP服務器:
//引入net模塊 var net=require('net'); //創建TCP服務器 var server=net.createServer(function(socket){ console.log('someone connets'); })
監聽客戶端的連接
使用TCP服務器的listen方法就可以開始監聽客戶端的連接:
server.listen(port[,host][,backlog][,callback]);
- port參數為需要監聽的端口號,參數值為0的時候將隨機分配一個端口號。
- host為服務器地址。
- backlog為等待隊列的最大長度
- callback為回調函數
下面代碼創建一個TCP服務器並監聽18001端口:
//引入net模塊 var net=require('net'); //創建TCP服務器 var server=net.createServer(function(socket){ console.log('someone connets'); }) server.listen(18001,function(){ console.log('server is listening'); });
當在瀏覽器中輸入http://localhost:18001/,連接成功后就會打印出someone connets字樣,表明createServer方法的回調函數已經執行,說明已經成功連接這個TCP服務器。
server.listen()方法其實觸發的是server下的listening事件,所以可以手動監聽listening事件。
下面代碼同樣實現創建一個TCP服務器並監聽18001端口的作用。
//引入net模塊 var net=require('net'); //創建TCP服務器 var server=net.createServer(function(socket){ console.log('someone connets'); }) //設置監聽端口 server.listen(18001); //設置監聽時的回調函數 server.on('listen',function(){ console.log('server is listening'); })
除listening事件外,TCP服務器還支持以下事件:
- connection:當前新的鏈接創建時觸發,回調函數的參數為socket連接對象。
- close:TCP服務器關閉的時候觸發,回調函數沒有參數
- error:TCP服務器發生錯誤的時候觸發,回調函數的參數為error對象
在下面代碼中將通過net.Server類創建一個TCP服務器,添加以上的事件:
//引入net模塊 var net=require('net'); //實例化一個服務器對象 var server=new net.Server(); //監聽connection事件 server.on('connection',function(){ console.log('someone connets'); }); //創建TCP服務器 var server=net.createServer(function(socket){ console.log('someone connets'); }); //設置監聽端口 server.listen(18001); //設置監聽時的回調函數 server.on('listen',function(){ console.log('server is listening'); }); //設置關閉時的回調函數 server.on('close',function(){ console.log('sever closed'); }); //設置出錯時的回調函數 server.on('error',function(){ console.log('error'); });
查看服務器監聽的地址
在創建一個TCP服務器之后可以通過server.address()方法來查看這個TCP服務器監聽的地址,並返回一個json對象,這個對象的屬性有:
- port:TCP服務器監聽的端口號;
- family:說明監聽的地址是IPV6還是IPV4
- address:TCP服務器監聽的地址。
因為這個方法返回的是TCP服務器監聽的地址信息,因此,這個方法應該在使用server.listen()方法或者綁定事件listening中的回調函數中的使用。
//引入net模塊 var net=require('net'); //創建服務器 var server=net.createServer(function(socket){ console.log('someone connets'); }); //設置監聽端口 server.listen(18001,function(){ //獲取地址信息 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 family of server is'+address.family); })
結果顯示:
連接服務器的客戶端數量
在創建一個TCP服務器的基礎下,可以通過server.getConnection()方法獲取連接這個TCP服務器的客戶端數量。這個方法是一個異步的方法,回調這個函數有兩個參數:
- 第一個參數為error對象
- 第二個參數為連接TCP服務器的客戶端數量。
除了獲取連接數量外,也可以通過設置TCP服務器的maxConnections屬性來設置這個TCP服務器最大連接數量。如果當連接的數量超過最大的數量的時候,服務器會拒絕新的連接。
在下面的代碼中設置創建這個TCP服務器的最大連接數量為3:
var net=require('net'); //創建服務器 var server=net.createServer(function(socket){ console.log('someone connects'); //設置連接最大數量 server.maxConnection=3; server.getConnections(function(err,count){ console.log('the count of clieent is'+count); }); }); //設置監聽端口 server.listen(18001,function(){ console.log('server is listening'); });
運行上面這段代碼,並嘗試用多個客戶端連接,可以發現當客戶端的連接數量超過3的時候,新的客戶端無法連接這個服務器。
獲取客戶端發送的數據
在上面我們提到了createServer/方法的回調函數參數是一個net.Socket對象(服務器所監聽的端口對象),這個對象同樣也有一個address()方法,用來獲取TCP服務器綁定的地址,同樣也返回一個含有port、family、address屬性的對象。
socket對象可以用來獲取客戶端發送的流數據,每次接收到的數據的時候觸發data事件,通過監聽這個事件就可以在回調函數中獲取客戶端發送的數據。
代碼:
var net=require('net'); //創建服務器 var server=net.createServer(function(socket){ //監聽dada事件 socket.on('data',function(data){ //打印data console.log(data.toString()); }); }); //設置監聽端口 server.listen(18001,function(){ console.log('server is listening'); });
效果顯示是在Google Chrome瀏覽器中輸入http://localhost:18001/打印出的信息,我們可以通過Telnet等工具連接后,發送一段數據給服務端,在命令行中就可以發現數據被打印出來:
獲取客戶端數據的效果:
socket對象除了有data事件外,還有connect,end、error、timeout等事件。
發送數據給客戶端
使用socket.write()可以使TCP服務器發送數據。這個方法只有一個必須參數,就是需要發送的數據;第二個參數為編碼格式,可選,同時,可以為這個方法設置一個回調函數,當有用戶連接TCP服務器的時候,將發送數據給客戶端
代碼:
var net=require('net'); //創建服務器 var server=net.createServer(function(socket){ //獲取地址信息 var address=server.address(); var message='client,the server address is'+JSON.stringify(address); //發送數據 socket.write(message,function(){ var writeSize=socket.bytesWritten; console.log(message+'has send'); console.log('the size of message is'+writeSize); }); //監聽dada事件 socket.on('data',function(data){ //打印data console.log(data.toString()); var readSize=socket.bytesRead; console.log('the size of data is'+readSize); }); }); //設置監聽端口 server.listen(18001,function(){ console.log('server is listening'); });
運行這段代碼並連接TCP服務器,可以看到Telnet中收到了TCP服務器發送的數據,Telnet也可以發送數據給TCP服務器:
在上面這段代碼中還用到了socket對象的bytesWritten和byteRead屬性,這兩個屬性分別代表着發送數據的字節數和接收數據的字節數。