node.js入門

網(wǎng)絡(luò)與IP

HTTP協(xié)議的底層是由TCP和IP協(xié)議(TCP/IP)構(gòu)建的

什么是TCP

TCP傳輸控制協(xié)議(Transmission Control Protocol):按層次分,TCP位于傳輸層,提供可靠的字節(jié)流服務(wù)。
換句話說蝙云,為了更容易的傳輸大數(shù)據(jù)硫嘶,TCP協(xié)議會把數(shù)據(jù)分割成以報文段為單位的數(shù)據(jù)包進行管理岔激,并且TCP協(xié)議能夠確認數(shù)據(jù)最終是否到達對方(一般指所謂的三次握手)刀闷。

  1. TCP與UDP的區(qū)別:
    簡答:TCP 可靠、面向連接瘦赫、相對 UDP 較慢;UDP 不可靠蛤迎,不面向連接确虱、相對 TCP 較快。搞定忘苛。
  2. TCP的三次握手:
    • 簡答:每次建立連接前蝉娜,客戶端和服務(wù)端之前都要先進行三次對話才開始正式傳輸內(nèi)容,三次對話大概是這樣的:
      1. 客戶端:我要連接你了扎唾,可以嗎
      2. 服務(wù)端:嗯召川,我準備好了,連接我吧
      3. 客戶端:那我連接你咯胸遇。
      4. 開始后面步驟
    • 詳細解答:握手過程中使用了TCP的標(biāo)志(flag)——SYG(synchronize)和ACG(acknowledge)
      1. 發(fā)送端:發(fā)送一個帶SYG標(biāo)志的數(shù)據(jù)包給對方
      2. 接收端:收到后荧呐,回傳一個帶SYG/ACK標(biāo)志的數(shù)據(jù)包以示傳達確認信息
      3. 發(fā)送端:收到后,再回傳一個帶ACK標(biāo)志的數(shù)據(jù)包纸镊,代表握手結(jié)束倍阐。

IP網(wǎng)絡(luò)協(xié)議(Internet Protocol)

從層次上分,IP網(wǎng)絡(luò)協(xié)議位于網(wǎng)絡(luò)層逗威,其作用是把各種數(shù)據(jù)包傳送給對方峰搪,為了確保數(shù)據(jù)傳送到正確的對象,則需要滿足一些條件凯旭,其中最重要的兩個便是:IP地址與MAC地址

  • IP地址指明了節(jié)點被分配到的地址
  • MAC地址是指的網(wǎng)卡所屬的固定地址

注意:
IP是一種網(wǎng)絡(luò)協(xié)議概耻,而IP地址是類似127.0.0.1的地址使套。
IP地址可以與MAC地址進行匹配。IP地址可換鞠柄,而MAC地址基本不會變侦高。

在互聯(lián)網(wǎng)中,一般一個設(shè)備對應(yīng)一個IP地址厌杜。通俗理解奉呛,IP地址分為內(nèi)網(wǎng)IP與外網(wǎng)IP


內(nèi)網(wǎng)與外網(wǎng)
  • 電信服務(wù)商提供DNS服務(wù),你從網(wǎng)頁中輸入的網(wǎng)址首先會去電信查找對應(yīng)的IP地址夯尽。
  • 路由器有一個「內(nèi)網(wǎng)IP」與一個「外網(wǎng)IP」瞧壮。
    • 內(nèi)網(wǎng)中的設(shè)備可以互相訪問(比如你可以用電腦或手機進入 http://192.168.1.1 來查看你的路由器),但是不能直接訪問外網(wǎng)呐萌,內(nèi)網(wǎng)設(shè)備想要訪問外網(wǎng)馁痴,就必須經(jīng)過路由器中轉(zhuǎn)。
    • 外網(wǎng)中的設(shè)備可以互相訪問(比如 qq.com 可以把首頁發(fā)送給你的路由器肺孤,你的路由器有外網(wǎng) IP)罗晕,但是外網(wǎng)中的設(shè)備無法訪問你的內(nèi)網(wǎng)設(shè)備。
    • 外網(wǎng)的資源通過路由器的中轉(zhuǎn)傳達至內(nèi)網(wǎng)的各個設(shè)備中赠堵,路由器在其中充當(dāng)指路人的角色小渊。
  • 路由器沒有固定的「外網(wǎng)IP」,都是臨時分配的茫叭,類似14.17.32.21酬屉,每次路由器重啟都會被重新分配一個IP地址。
  • 路由器與其wifi組成整個內(nèi)網(wǎng)揍愁,在內(nèi)網(wǎng)中的每個設(shè)備都有一個對應(yīng)的「外網(wǎng)IP」呐萨,類似192.168.1.1,這個內(nèi)網(wǎng)IP也不是固定的莽囤,一般設(shè)備斷開wifi重連都會改變內(nèi)網(wǎng)IP地址谬擦。
  • 兩個特殊的IP,本地IP 127.0.0.1 代表設(shè)備自身朽缎,特別的IP 0.0.0.0 不表示任何設(shè)備惨远。

端口

端口其實就是一個編號,并不是一種硬件话肖。
一個服務(wù)器(硬件)不一定只提供一種服務(wù)北秽,比如一個服務(wù)器既提供 HTTP 服務(wù),又提供 FTP 服務(wù)最筒,還提供 SMTP 服務(wù)(郵件服務(wù))贺氓,那么只用一個 IP 是無法告訴服務(wù)器你想要使用哪種服務(wù)。

所以這里有一個重要的原則:一個端口對應(yīng)一個服務(wù)床蜘。

  • HTTP服務(wù) 80端口
  • HTTPS服務(wù) 443端口
  • FTP服務(wù) 21端口

每個機器一共有65535(2的16次方減一)個端口(協(xié)議規(guī)定)

  1. 0到1023(2的10次方減一)號端口留給系統(tǒng)使用掠归。
  2. 其他端口用戶用
  3. 如果端口被占用缅叠,需要停掉該端口的服務(wù)才能再次使用。

寫一個簡易的HTTP Server

創(chuàng)建一個后臺服務(wù)

任何網(wǎng)絡(luò)服務(wù)應(yīng)用程序總是要先創(chuàng)建一個服務(wù)對象虏冻。這在 Node.js 中通常通過 createServer 方法。

var http = require('http');

var server = http.createServer(function(request, response) {
  // magic happens here!
});

每當(dāng)有 HTTP 請求到達服務(wù)器時弹囚,createServer 中傳入的函數(shù)就被自動執(zhí)行厨相。所以這個函數(shù)也被稱為是請求處理函數(shù)。
當(dāng)一個 HTTP 到達服務(wù)端鸥鹉,node 調(diào)用 request 處理程序蛮穿,并產(chǎn)生一些唾手可得的對象用以處理傳輸,這些對象就是 request 和 response毁渗。践磅。

監(jiān)聽端口

實際上,為了處理請求灸异,listen 方法需要在 server 對象上被顯式調(diào)用府适。在大多數(shù)情況下,你只要把端口號作為參數(shù)傳入 listen 方法中肺樟,作為監(jiān)聽端口即可檐春。

var port = process.argv[2]//命令的第三個參數(shù)

server.listen(port)

請求方法、訪問地址以及請求頭

當(dāng)處理一個請求時么伯,第一件事你需要做的是看一下這個方法和其訪問地址疟暖,以此決定你到底采取何種合理的行為。Node 通過把這些行為屬性附加到 request 對象上田柔,使得我們處理起來相對而言可以輕松一些俐巴。

var method = request.method
var path = request.url

這里的 method 總是一個普通的 HTTP 方法動作行為 (verb),path 是指沒有服務(wù)器協(xié)議和 端口號的完整訪問地址硬爆。一個典型的訪問地址通常意味著包括第三個斜杠以及后面的所有內(nèi)容欣舵。
請求頭也不是很難得到,它們也在 request 對象里摆屯,稱為 headers邻遏。

var headers = request.headers
var userAgent = headers['user-agent']

所有的請求頭全是小寫字母,而不管實際上它們是怎么進行傳輸?shù)呐捌铩K栽跓o論任何 情況下准验,解析請求頭就得到了簡化。
如果一些請求頭出現(xiàn)重復(fù)廷没,它們的值不是被覆蓋糊饱,就是通過英文分號進行分割。

設(shè)置響應(yīng)頭

響應(yīng)頭通過一個 setHeader 的屬性很方便的設(shè)置颠黎。

response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');

設(shè)置響應(yīng)頭時另锋,它們的名字是大小寫敏感的滞项。如果你重復(fù)設(shè)置響應(yīng)頭,最后一次設(shè)置的值也就是系統(tǒng)得到的值夭坪。

發(fā)送響應(yīng)體

既然 response 對象是一個 WritableStre文判,向客戶端寫入返回體只是一個普通的流方法的問題。

response.write('<!DOCTYPE>\n<html>'  + 
      '<head><link rel="stylesheet" href="/style.js">' +
      '</head><body>'  +
      '<h1>你好</h1>' +
      '<script src="/script.html"></script>' +
      '</body></html>')
response.end();

也可以將響應(yīng)體放在end方法中室梅。

關(guān)于錯誤

請求與響應(yīng)若是發(fā)生錯誤戏仓,則會自動觸發(fā)自身的error事件。如果你不去處理監(jiān)聽這個事件亡鼠,此錯誤將被拋出赏殃,這導(dǎo)致你的程序崩潰。 你應(yīng)該無論如何都要添加 'error' 事件去監(jiān)聽你的請求對象间涵,哪怕你只是做一個日志或者用你自己的獨有方式去處理仁热。

request.on('error', function() {
  // This prints the error message and stack trace to `stderr`.
  console.error(err);
});

response.on('error', function() {
  // This prints the error message and stack trace to `stderr`.
  console.error(err);
});

HTTP 狀態(tài)碼

如果你嫌麻煩不想設(shè)置它,返回客戶端的默認狀態(tài)碼總是 200勾哩。當(dāng)然抗蠢,不是每個 HTTP 返回碼必須都是 200,在某些情況下你一定希望返回一個不同的狀態(tài)碼钳幅,所以你應(yīng)該設(shè)置 statusCode 屬性物蝙。

response.statusCode = 404;

代碼示例

var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('請指定端口號好不啦?\nnode server.js 8888 這樣不會嗎敢艰?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var path = request.url 
  var query = ''
  if(path.indexOf('?') >= 0){ query = path.substring(path.indexOf('?')) }
  var pathNoQuery = parsedUrl.pathname
  var queryObject = parsedUrl.query
  var method = request.method

  /******** 從這里開始看诬乞,上面不要看 ************/

  console.log('HTTP 路徑為\n' + path)
  if(path == '/style.js'){
    response.setHeader('Content-Type', 'text/css; charset=utf-8')
    response.write('body{background-color: #ddd;}h1{color: red;}')
    response.end()
  }else if(path == '/script.html'){
    response.setHeader('Content-Type', 'text/javascript; charset=utf-8')
    response.write('alert("這是JS執(zhí)行的")')
    response.end()
  }else if(path == '/index.css'){
    response.setHeader('Content-Type', 'text/html; charset=utf-8')
    response.write('<!DOCTYPE>\n<html>'  + 
      '<head><link rel="stylesheet" href="/style.js">' +
      '</head><body>'  +
      '<h1>你好</h1>' +
      '<script src="/script.html"></script>' +
      '</body></html>')
    response.end()
  }else{
    response.statusCode = 404
    response.end()
  }

  /******** 代碼結(jié)束,下面不要看 ************/
})

server.listen(port)
console.log('監(jiān)聽 ' + port + ' 成功\n請用在空中轉(zhuǎn)體720度然后用電飯煲打開 http://localhost:' + port)

以上內(nèi)容參考node官網(wǎng),感興趣的可以去看看钠导。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末震嫉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子牡属,更是在濱河造成了極大的恐慌票堵,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逮栅,死亡現(xiàn)場離奇詭異悴势,居然都是意外死亡,警方通過查閱死者的電腦和手機措伐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門特纤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侥加,你說我怎么就攤上這事捧存。” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵昔穴,是天一觀的道長镰官。 經(jīng)常有香客問我,道長吗货,這世上最難降的妖魔是什么泳唠? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮卿操,結(jié)果婚禮上警检,老公的妹妹穿的比我還像新娘。我一直安慰自己害淤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布拓售。 她就那樣靜靜地躺著窥摄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪础淤。 梳的紋絲不亂的頭發(fā)上崭放,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音鸽凶,去河邊找鬼币砂。 笑死,一個胖子當(dāng)著我的面吹牛玻侥,可吹牛的內(nèi)容都是我干的决摧。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼凑兰,長吁一口氣:“原來是場噩夢啊……” “哼掌桩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姑食,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤波岛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后音半,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體则拷,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年曹鸠,在試婚紗的時候發(fā)現(xiàn)自己被綠了煌茬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡物延,死狀恐怖宣旱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叛薯,我是刑警寧澤浑吟,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布笙纤,位于F島的核電站,受9級特大地震影響组力,放射性物質(zhì)發(fā)生泄漏省容。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一燎字、第九天 我趴在偏房一處隱蔽的房頂上張望腥椒。 院中可真熱鬧,春花似錦候衍、人聲如沸笼蛛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滨砍。三九已至,卻和暖如春妖异,著一層夾襖步出監(jiān)牢的瞬間惋戏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工他膳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留响逢,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓棕孙,卻偏偏與公主長得像舔亭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子散罕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 名詞延伸 通俗的說,域名就相當(dāng)于一個家庭的門牌號碼误甚,別人通過這個號碼可以很容易的找到你缚甩。如果把IP地址比作一間房子...
    楊大蝦閱讀 20,593評論 2 57
  • 1、TCP為什么需要3次握手窑邦,4次斷開擅威? “三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端...
    杰倫哎呦哎呦閱讀 3,475評論 0 6
  • 1.這篇文章不是本人原創(chuàng)的,只是個人為了對這部分知識做一個整理和系統(tǒng)的輸出而編輯成的冈钦,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,053評論 6 174
  • 文章首發(fā)于個人blog歡迎指正補充郊丛,可聯(lián)系lionsom_lin@qq.com原文地址:《網(wǎng)絡(luò)是怎樣連接的》閱讀整...
    lionsom_lin閱讀 14,135評論 6 31
  • 個人認為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,051評論 0 8