TCP、HTTP和Node.js的那些事

ReneeTsang發表於2018-04-24

TCP

TCP是用來計算機之間進行通訊的,通過編寫客戶端和服務端聊天的程式碼,對於伺服器與客戶端的工作步驟有了深刻的瞭解。在node中為了實現TCP,提供了一個net模組,net 模組給你提供了一個非同步的網路封裝,它包含建立伺服器和客戶端(稱為流)的功能。

建立TCP服務端

  • net.createServer(options,connectionListener);

建立一個tcp服務,裡面放的是回撥函式 監聽函式,當連線到來時才會執行。

其中傳進去的引數socket是套接字,幫我們實現會話,每一個客戶端對應的socket都是不一樣的。是一個duplex雙工流,可以支援讀操作和寫操作。

  • server.listen()

可以設定服務監聽的埠,主機名, backlog服務端處理的最大請求,預設是511,可以不寫。還有回撥函式,當服務啟動成功會呼叫

let net = require('net');
let server = net.createServer(function(socket){
    ...
})
server.listen(8080,'localhost',function(){
    console.log(`server start 8080`)
});複製程式碼

接下來可以對服務端進行配置

設定一個服務端最大的連結數

server.maxConnections = 6;複製程式碼

得到連線的時候觸發方法

希望每次請求到來時都有一個提示,當前最大連線多少個,現在一共連線多少個

server.getConnections(function(err,count){ 
    socket.write(`當前最大容納${server.maxConnections},現在${count}人`)
});複製程式碼

接受客戶端資料

  • 讀取客戶端的輸入

socket.on('data',function(data){
    console.log(data); 
});複製程式碼
  • 暫停讀取

socket.pause();複製程式碼
  • 恢復讀取

socket.resume();複製程式碼

pipe&unpipe

監聽客戶輸入時,將客戶端輸入的內容寫入到檔案內容。

如果有兩個客戶端,就有兩個socket,其中一個關閉了,另一個就寫不進去了

let net = require('net');
let path = require('path');
let ws = require('fs').createWriteStream(path.join(__dirname,'./1.txt'));
let server = net.createServer(function(socket){
    socket.pipe(ws,{end:false}); // 所以可以設定這個可寫流不關閉
    setTimeout(function(){
        ws.end(); // 關閉可寫流
        socket.unpipe(ws); // 取消管道,就不能傳輸了
    },5000)
});
server.listen(8080);複製程式碼

關閉客戶端

  • socket.end(); 除了手動關閉,我們也可以呼叫此方法讓它關閉。

關閉服務端

  • server.close();

close事件表示服務端不在接收新的請求了,當前的還能繼續使用,當客戶端全部關閉後會執行close事件。

// close事件只有呼叫close方法才會觸發
server.on('close',function(){
    console.log('服務端關閉');
})複製程式碼
  • server.unref();

unref() 不會觸發close事件,只有當所有客戶端都關閉了,服務端才關閉,如果有人進來(有新請求)仍然可以。

建立TCP客戶端

  • net.createConnection 是用來建立於服務端的連線

let net = require('net');
​
let socket = net.createConnection({port:8080},function(){
    socket.write('hello');
    socket.on('data',function(data){
        console.log(data);
    });
});複製程式碼

HTTP

node中為了實現http同樣也提供了一個模組,叫http模組,其中封裝了高效的http伺服器和http客戶端 ,與net模組用法相似。

建立HTTP伺服器

  • request

當客戶端請求到來的時候,該事件被觸發。

我們最常用的還是request事件,http也給這個事件提供了一個捷徑:http.createServer([requestListener])

  • 引數res req

傳入中的引數req是請求,是一個可讀流,res是響應 是一個可寫流。是通過socket解析出來請求和響應。

建立HTTP伺服器有兩種方法

  1. 第一種

let http = require('http'); 
let server = http.createServer();
server.on('request',function(req,res){
    req.on('end',function(){
        res.write('hello');
        res.end('world');
    });
});
server.listen(8080);複製程式碼
  1. 可以這樣簡寫

let http = require('http');
let server = http.createServer(function(req,res){
  res.end('ok');
});
server.listen(8080);複製程式碼

關閉HTTP伺服器

let http = require('http');
let server = http.createServer(function(req,res){
});
server.on('close',function(){
    console.log('伺服器關閉');
});
server.listen(8080,'127.0.0.1',function(){
    console.log('伺服器端開始監聽!')
    server.close(); // 關閉
});複製程式碼

建立HTTP客戶端

http 模組提供了兩個函式 http.request 和 http.get,功能是作為客戶端向 HTTP伺服器發起請求。

  • http.request(options, callback) 發起 HTTP 請求。接受兩個引數,option 是一個類似關聯陣列的物件,表示請求的引數,callback 是請求的回撥函式。

let http = require('http');
let options = {
    hostname:'localhost',
    port:4000,
    path: '/',
    method:'get',
    // 告訴服務端我當前要給你發什麼樣的資料
    headers:{
        'Content-Type':'application/x-www-form-urlencoded',
        'Content-Length':17
    }
}
let req = http.request(options);
// 當客戶端收到伺服器響應的時候觸發
req.on('response',function(res){
    res.on('data',function(chunk){
        console.log(chunk);
    });
});
req.end('name=renee&&age=18');複製程式碼
  • http.get(options, callback) http 模組還提供了一個更加簡便的方法用於處理GET請求:http.get。它是 http.request 的簡化版,唯一的區別在於http.get自動將請求方法設為了 GET 請求,同時不需要手動呼叫 req.end()。

var http = require('http');
​
http.createServer(function(req,res){}).listen(3000);
​
http.get('http://www.baidu.com/index.html',function(res){
    console.log('get response Code :' + res.statusCode);
}).on('error',function(e){
    console.log("Got error: " + e.message);
})複製程式碼


相關文章