1、實現「Hello World!」及相關API介紹html
使用 HTTP 服務器和客戶端必須使用 require('http')node
Node.js 中的 HTTP 接口設計主要是爲了支持 傳統的很難使用的多特性的協議,尤爲是大量的信息。接口沒有緩衝整個接收和相應,用戶可以使用流式數據。
linux
HTPP信息的頭部是像一個對象那樣描述的:
api
{ 'content-length': '123', 'content-type': 'text/plain', 'connection': 'keep-alive', 'host': 'mysite.com', 'accept': '*/*' }
http.createServer([requestListener])數組
Returns: <http.Server>瀏覽器
返回一個新的 http.Server 的實例
服務器
requestListener 是一個自動添加 'request'
的函數異步
server.listen([port][, hostname][, backlog][, callback])socket
開始接受指定的端口號(port)和主機名(hostname)之間的鏈接。tcp
參數類型:
port:Number
hostname:String
backlog:Number
callback:Function
若是省略了 hostname,當IPV6可用時,服務器將鏈接任意的IPV6地址(::
),或者是任意的IPV4地址 (0.0.0.0
)
忽略 port 參數或者使用 0 做爲端口號,若是想讓操做系統隨機分配一個端口號,能夠在 'listening'
事件以後使用 server.address().port 來從新取回
若是想要監聽 unix 套接字,能夠用一個文件名來替換 port 和 hostname
backlog 是鏈接請求隊列的最大長度,實際的長度將由你的 OS 經過系統調用設置來決定,好比 linux 上的 tcp_max_syn_backlog 和 somaxconn 。這個參數的默認值是511(不是512)
callback 做爲 'listening'
事件的一個監聽器, 是一個異步的回調函數
response.writeHead(statusCode[, statusMessage][, headers])
給請求消息發送一個響應頭
statusCode Number 類型, 是一個三位數的 HTTP 狀態碼 好比:404
statusMessage String 類型,是可選的,主要是提升可讀性
headers Object 類型, 是一個響應頭,第二個參數是可選的
例如:
var body = 'hello world';response.writeHead(200, { 'Content-Length': Buffer.byteLength(body), 'Content-Type': 'text/plain' });
此方法在一個消息上只能調用一次,且必須在 response.end()
以前調用
response.end([data][, encoding][, callback])
這個方法是用來告訴服務器,全部的響應頭和響應主體已經發送完畢,服務器就會知道這個消息已經完成了。每個響應消息都必須調用 response.end()
encoding
<String>
callback
<Function>
若是指定了 data ,就至關於在 response.end(callback) 以前調用了 response.write(data, encoding)
若是指定了 callback ,將在響應流結束以後調用
結合以上內容,咱們再來看一下經典的 Node.js 入門案例,在頁面打印「Hello World」
基本的骨架:
//第一步: 引入 http 模塊 var http = require('http'); //第二步:建立一個服務器(requestListener 是一個函數,裏面有2個參數,一個請求消息,一個響應消息) var server = http.createServer(function(req, res){ }); //第三步:服務器監聽本地的82端口 server.listen(8082, '127.0.0.1');
設置消息內容:
var server = http.createServer(function(req, res){ //req -> request,表示請求; res -> response,表示響應 //設置響應頭,第一個參數是3位數的HTTP狀態碼,第二個參數可選,第三個參數是一個對象,裏面可存放合法的MIME類型 //MIME類型:文件類型是純文本,字符集編碼方式是 utf8 res.writeHead(200,{'Content-Type': 'text/plain; charset=utf8'}); //響應消息發送結束,若是指定了data參數,就至關於在 res.end() 以前添加了一個 res.end(data, encoding) 方法 //res.end('Hello World!', 'utf8'); res.end('Hello World!'); });
經過命令行工具掛起服務器,打開瀏覽器,在地址欄輸入: 127.0.0.1:8082
同時,也能夠打開控制檯查看請求頭部
值得注意的是,若是省略了 res.end(), 頁面是渲染不出來的,由於服務器會一直處於等待狀態,沒人告訴它響應消息是否結束了
在 Node.js 三大特色詳解 一文中,咱們瞭解到傳統的 HTTP服務器通常創建在 Apache、Nginx、IIS等服務器上,而 Node.js 並不須要,因爲 Node.js 提供了 http 模塊,自身就能夠構建服務器(從上面的例子能夠體會到)。
http 模塊 是經過 C++實現的,性能很是可靠,其中,封裝了一個 http 服務器 和一個簡易的 http 客戶端。http.Server 是一個基於事件的 http 服務器,http.request 則是一個 http 客戶端工具,用於向 http 服務器發起請求
前面提到的 http.createServer( requestListener ) 方法中,requestListener 是一個回調函數,函數有2個參數 request 和 response,request 是 http.IncomingMessage 對象的實例,response 是 http.ServerResponse 對象的實例。下面分別來學習 HTTP 服務器 和 HTTP 客戶端。
2、HTTP 服務器
先回顧下「Hello World!」這個例子
//第一步: 引入 http 模塊 var http = require('http'); //第二步:建立一個服務器(requestListener 是一個函數,裏面有2個參數,一個請求消息,一個響應消息) var server = http.createServer(function(req, res){ //req -> request,表示請求; res -> response,表示響應 //設置響應頭,第一個參數是3位數的HTTP狀態碼,第二個參數可選,第三個參數是一個對象,裏面可存放合法的MIME類型 //MIME類型:文件類型是純文本,字符集編碼方式是 utf8 res.writeHead(200,{'Content-Type': 'text/plain; charset=utf8'}); //響應消息發送結束,若是指定了data參數,就至關於在 res.end() 以前添加了一個 res.end(data, encoding) 方法 //res.end('Hello World!', 'utf8'); res.end('Hello World!'); }); //第三步:服務器監聽本地的82端口 server.listen(8082, '127.0.0.1');
基本的結構是直接建立一個 http 對象,而後建立一個 http 對象的實例 server,併爲其監聽82端口
一、http.Server
http.Server 繼承自 net.Server
而 net.Server是一個 EventEmitter
,主要用來建立一個 TCP或者本地服務器。
事實上,Node.js 中大部分模塊都繼承自 EventEmitter,包括fs、net等模塊,這也是爲何說 Node.js 基於事件驅動。http.Server 提供的事件以下:
request
客戶端發出請求時觸發,每一次鏈接可能會發出不少個請求(假如是持久鏈接的話)。提供兩個參數request 和 response,是最經常使用的事件
request
<http.IncomingMessage>
response
<http.ServerResponse>
connection
當 TCP 創建鏈接時,觸發此事件,提供一個參數 socket,是 net.socket 的實例
socket
<net.Socket>
close
當服務器關閉時,觸發此事件。注意不是用戶斷開鏈接時
除此以外還有 checkContinue,upgrade,clientError 等事件,只有在實現複雜的 HTTP 服務器的時候纔會用到。
在這些事件中,最經常使用的就是 request 事件,因此,http 提供了一個捷徑:http.createServer( requestListener ),如咱們所知,功能就是建立一個 HTTP 服務器並將 requestListener 做爲 request 事件的監聽函數,
二、http.IncomingMessage --> request
http.IncomingMessage 是 HTTP 請求的信息,通常由 http.Server 的 request 事件發送,並做爲第一個參數傳遞,http 請求通常包括 請求頭部 和 請求主體。
其提供了三個事件用於控制請求體傳輸:
data: 當請求體數據到來時,觸發該事件。該事件提供一個參數 chunk,表示接收到的數據。若是該事 件沒有被監聽,那麼請求體將會被拋棄,該事件可能會被調用屢次
end:當請求體數據傳輸完成時,該事件被觸發,此後將不會再有數據到來
close:用戶當前請求結束時,該事件被觸發。不一樣於end,若是用戶強制終止傳輸,也仍是調用 close
http.IncomingMessage 的屬性以下:
三、http.ServerResponse ---> response
http.ServerResponse 是返回給客戶端的信息,決定了用戶最終能看到的結果。它是由 http.Server 的 request 事件發送的,做爲第二個參數傳遞,通常簡稱爲 response 或 res
http.ServerResponse 有三個重要的成員函數,用於返回響應頭、響應內容以及結束請求(上面已經介紹過,這裏再複習一次)
response.writeHead(statusCode[, statusMessage][, headers]): 向請求的客戶端發送響應頭
statusCode 是 HTTP狀態碼,經常使用的好比 200(請求成功),404(未找到)
headers 是一個相似關聯數組的對象,表示響應頭的每一個屬性
此函數在一個請求內最多隻能調用一次,若是不調用,則會自動生成一個響應頭
response.write(data, [encoding]): 向請求的客戶端發送響應內容
data 是一個 Buffer 或字符串,表示要發送的內容。若是data 是字符串,那麼須要指定 encoding 來講明它的編碼方式,默認是 utf-8。在 response.end 調用以前,response.write 能夠被屢次調用
response.end([data], [encoding]): 結束響應
告知客戶端全部發送已經完成,當全部要返回的內容都發送完畢的時候,該函數必須被調用一次。
此函數接受兩個可選參數,意義和 response.write 相同,若是不調用此函數,客戶端將用於處於等待狀態(前面的案例提到過)
3、HTTP 客戶端
http 模塊提供了兩個函數 http.request 和 http.get,功能是做爲客戶端向 HTTP 服務器發起請求
一、http.request(options, callback) 發起 HTTP 請求
接受兩個參數,options表示請求的參數,能夠是一個對象或字符串,若是是字符串的話,將自動調用 url.parse()
解析;
callback 是請求的回調函數,須要傳遞一個參數
options 經常使用的參數以下:
host:請求網站的域名或 IP 地址
port:請求網站的端口號,默認 80
method:請求方法,默認是 GET
path:請求的相對於根的路徑,默認是「/」。QueryString 應該包含在其中,例如:/search?query=byvoid
headers:一個關聯數組對象,爲請求頭的內容
http.request() 返回一個 http.ClientRequest
的實例
示例代碼:
var http=require("http"); var options={ hostname:"www.12306.cn", port:80 }; var req=http.request(options,function(res){ res.setEncoding("utf-8"); res.on("data",function(chunk){ console.log(chunk.toString()) }); console.log(res.statusCode); }); req.on("error",function(err){ console.log(err.message); }); req.end();
咱們運行這段代碼,就能夠在控制檯中看到 12036 的 HTML 代碼了
二、http.get(options, callback)
因爲大多數的 GET 請求都沒有主體,因此 Node.js 提供了這個簡便的方法用於處理 GET 請求。
此方法是 http.request 的簡化版,惟一的區別在於 http.get 自動將請求方法設爲了 GET 請求,同時不須要手動調用 req.end()
var http = require('http'); http.get({host: 'www.12306.cn'}, function(res) { res.setEncoding('utf8'); res.on('data', function (data) { console.log(data); }); });
運行這段代碼,同樣能夠在控制檯獲得 12036 的 HTML 代碼
三、http.ClientRequest
http.ClientRequest 是由 http.request 或 http.get 返回產生的對象,表示一個已經產生並且正在進行中的 HTTP 請求。
它提供了一個 response 事件,即 http.request 或 http.get,第二個參數指定的回調函數的綁定對象。咱們能夠顯示地綁定這個事件的監聽函數:
var http = require('http'); var req = http.get({host: 'www.12306.cn'}); req.on('response', function(res) { res.setEncoding('utf8'); res.on('data', function (data) { console.log(data); }); });
運行這段代碼,同樣能夠在控制檯獲得 12036 的 HTML 代碼
http.ClientRequest 像 http.ServerResponse 同樣也提供了 write 和 end 函數,用於向服務器發送請求體,一般用於 POST、PUT 等操做。全部寫結束之後必須調用 end 函數以通知服務器,不然請求無效。
http.ClientRequest 還提供瞭如下函數。
request.abort():終止正在發送的請求。
request.setTimeout(timeout, [callback]):設置請求超時時間,timeout 爲毫秒數。當請求超時之後,callback 將會被調用。
四、http.ClientResponse
http.ClientResponse 與 http.ServerRequest 類似,提供了三個事件 data、end和 close,分別在數據到達、傳輸結束和鏈接結束時觸發,其中 data 事件傳遞一個參數chunk,表示接收到的數據。
http.ClientResponse 也提供了一些屬性,用於表示請求的結果狀態
http.ClientResponse 還提供瞭如下幾個特殊的函數。
response.setEncoding([encoding]):設置默認的編碼,當 data 事件被觸發時,數據將會以 encoding 編碼。默認值是 null,即不編碼,以 Buffer 的形式存儲。經常使用編碼爲 utf8。
response.pause():暫停接收數據和發送事件,方便實現下載功能。
response.resume():從暫停的狀態中恢復。