摘要:中可以利用模塊進(jìn)行服務(wù)器的搭建。每個(gè)響應(yīng)都必須調(diào)用方法,并且在最后調(diào)用。中后面的部分叫做。方法封裝了和方法常識(shí)模塊的服務(wù)器默認(rèn)返回的數(shù)據(jù)類(lèi)型是模塊中的屬性包含所有的狀態(tài)碼及其描述信息
使用Node進(jìn)行網(wǎng)絡(luò)開(kāi)發(fā)
用戶(hù)在瀏覽器中輸入網(wǎng)址 --> 獲得網(wǎng)頁(yè)的過(guò)程經(jīng)歷了幾個(gè)步驟:
通過(guò)瀏覽器發(fā)送一個(gè)請(qǐng)求到服務(wù)器(期間經(jīng)歷的DNS解析、TCP3次握手連接)
服務(wù)器分析、處理用戶(hù)的請(qǐng)求,并生產(chǎn)請(qǐng)求的內(nèi)容,然后發(fā)送給瀏覽器
瀏覽器解析服務(wù)發(fā)送回的數(shù)據(jù),生產(chǎn)網(wǎng)頁(yè)
服務(wù)器在HTTP協(xié)議中的服務(wù)器指:監(jiān)聽(tīng)客戶(hù)端的請(qǐng)求,并且根據(jù)請(qǐng)求的內(nèi)容進(jìn)行相應(yīng)處理,返回響應(yīng)給客戶(hù)端。
Node中可以利用http模塊進(jìn)行Web服務(wù)器的搭建。
http模塊http模塊不是Node的核心模塊,需要利用require()加載
使用http.createServer()方法創(chuàng)建一個(gè)http服務(wù)器,返回一個(gè)http服務(wù)器對(duì)象
利用服務(wù)器對(duì)象進(jìn)行開(kāi)發(fā)
接收的回調(diào)函數(shù)是監(jiān)聽(tīng)到客戶(hù)端請(qǐng)求時(shí)的回調(diào)函數(shù)
server.listen()方法可以開(kāi)啟Web服務(wù),監(jiān)聽(tīng)某臺(tái)主機(jī)的某個(gè)端口
參數(shù)是(port, hostname, backlog, callback)
port是監(jiān)聽(tīng)主機(jī)的端口號(hào);hostname是監(jiān)聽(tīng)主機(jī)的IP地址;callback是服務(wù)器成功開(kāi)啟后的回調(diào)函數(shù)(開(kāi)啟服務(wù)器后,再連接數(shù)據(jù)庫(kù))
// 搭建一個(gè)HTTP服務(wù)器,用于處理用戶(hù)發(fā)送的http請(qǐng)求 // http模塊不是核心模塊,需要require()導(dǎo)入 var http = require("http"); // http模塊的createServer()方法可以返回一個(gè)標(biāo)準(zhǔn)http服務(wù)器對(duì)象 // 通過(guò)服務(wù)器對(duì)象來(lái)進(jìn)行開(kāi)發(fā) // callback是監(jiān)聽(tīng)到客戶(hù)端連接的回調(diào)函數(shù) var server = http.createServer(callback); // 服務(wù)器監(jiān)聽(tīng)某個(gè)網(wǎng)卡上的某個(gè)端口,開(kāi)啟服務(wù) // listen(port, hostname, backlog, callback) // port是監(jiān)聽(tīng)的端口,hostname是監(jiān)聽(tīng)主機(jī)的ip地址,callback是服務(wù)器開(kāi)啟成功后的回調(diào)函數(shù) // 服務(wù)器開(kāi)啟失敗時(shí)觸發(fā)error事件 server.on("error", function (err) { console.log(err); }) // listening事件在服務(wù)器開(kāi)啟成功時(shí)觸發(fā) server.on("listening", function () { console.log("listening...8080"); }) // 監(jiān)聽(tīng)來(lái)自客戶(hù)端的請(qǐng)求事件,在接收到請(qǐng)求時(shí)觸發(fā) server.on("request", function () { console.log("there is a request"); }) server.listen(8080, "localhost");主要的事件
服務(wù)器開(kāi)啟失敗的事件error的監(jiān)聽(tīng):server.on("errro", function(err) {})
服務(wù)器開(kāi)啟成功的事件listening的監(jiān)聽(tīng):server.on("listening", function(err) {}),可以寫(xiě)在server.listen()方法的回調(diào)函數(shù)中
服務(wù)器接收到請(qǐng)求的事件request的監(jiān)聽(tīng):server.on("request", function(err, req, res) {}),可以寫(xiě)在http.createServer()方法的回調(diào)函數(shù)中
參數(shù)對(duì)象request事件接收兩個(gè)參數(shù):
request對(duì)象:提供客戶(hù)端請(qǐng)求相關(guān)數(shù)據(jù)的對(duì)象,是http.IncomingMessage類(lèi)的一個(gè)實(shí)例,有對(duì)應(yīng)的屬性與方法
httpVersion屬性:使用的HTTP協(xié)議版本
header屬性:請(qǐng)求頭中相關(guān)的數(shù)據(jù)
url屬性:
method屬性:請(qǐng)求的方式
...
response對(duì)象:服務(wù)端向客戶(hù)端發(fā)送的響應(yīng)數(shù)據(jù)對(duì)象,是http.ServerResponse類(lèi)的一個(gè)實(shí)例
write(chunk, [encoding]):發(fā)送一個(gè)數(shù)據(jù)庫(kù)到響應(yīng)的正文(網(wǎng)頁(yè)的內(nèi)容數(shù)據(jù))中,需要在發(fā)送完成后調(diào)用res.end()方法
end(chunk, [encoding], [callback]):在通過(guò)write()方法發(fā)送完所有正文和頭信息后,需要res.end()告訴服務(wù)器數(shù)據(jù)全部發(fā)送完成。每個(gè)響應(yīng)都必須調(diào)用res.end()方法,并且在最后調(diào)用。
如果指定了 chunk,則它等同于調(diào)用 response.write(chunk, encoding) 之后調(diào)用 response.end(callback)
writeHeader(statusCode [, statusMessage] [, headers]):寫(xiě)入頭信息,在res.write()前調(diào)用,并且一次響應(yīng)中只能調(diào)用一次,頭信息寫(xiě)在一個(gè)對(duì)象中
statusCode屬性和setHeader()方法可以組合實(shí)現(xiàn)writeHeader()的功能
server.on("request", function (req, res) { console.log("there is a request"); var chunk = "url處理hello world
"; // Buffer.byteLength(chunk)以字節(jié)為單位,告訴瀏覽器以純文本解析傳回的數(shù)據(jù) res.writeHeader(200, "OK", {"Content-type": "text/plain", "Content-length": Buffer.byteLength(chunk)}); res.end(chunk, "utf-8"); })
根據(jù)用戶(hù)請(qǐng)求的path返回不同的數(shù)據(jù),使用req.url可以獲取path信息。
req.url中?后面的部分叫做query。
Node下的url模塊可以處理請(qǐng)求的中的req.url
使用switch結(jié)構(gòu),為不同的pathname劃分不同的邏輯處理方式
server.on("request", function (req, res) { console.log(req.url); // req.url獲取請(qǐng)求的路徑path信息 var urlStr = url.parse(req.url); switch(urlStr.pathname) { case "/": // 首頁(yè) res.writeHeader(200, "OK", {"Content-type": "text/plain"}); res.end("使用fs模塊實(shí)現(xiàn)行為與表現(xiàn)分離首頁(yè)
", "utf-8"); break; case "/users": // 用戶(hù)頁(yè) res.writeHeader(200, "OK", {"Content-type": "text/plain"}); res.end("用戶(hù)頁(yè)
", "utf-8"); break; default : // 不存在 res.writeHeader(404, "Not Found", {"Content-type": "text/plain"}); res.end("出錯(cuò)
", "utf-8"); break; } })
根據(jù)用戶(hù)不同訪問(wèn)的不同路徑,執(zhí)行不同操作,讀取不同頁(yè)面
server.on("request", function (req, res) { console.log(req.url); var urlStr = url.parse(req.url); switch(urlStr.pathname) { case "/": // 首頁(yè) sendData(htmlDir + "/index.html", req, res); // 請(qǐng)求不同的路徑,讀取不同的頁(yè)面返回給客戶(hù)端 break; case "/users": // 用戶(hù)頁(yè) sendData(htmlDir + "/user.html", req, res); break; default : // 不存在 sendData(htmlDir + "/404.html", req, res); break; } }); // 每次請(qǐng)求都讀取靜態(tài)頁(yè)面,再輸出。 fs.readFile()方法封裝了fs.open()、fs.read()和fs.close()方法 // fs.readFile()返回值是原始的buffer對(duì)象 function sendData(file, req, res) { fs.readFile(file, function (err, data) { if(err) { res.writeHeader(404, "Not Found", {"Content-Type": "text/html"}); res.end("Not Found"); } else { res.writeHeader(200, "OK", {"Content-Type": "text/html"}); res.end(data); } }); }處理GET與POST請(qǐng)求提交的數(shù)據(jù)
通過(guò)GET方法傳遞的數(shù)據(jù)可以使用url.parse(req.url).query獲取到GET請(qǐng)求提交的數(shù)據(jù),使用querystring內(nèi)置模塊(無(wú)需加載)來(lái)解析
GET請(qǐng)求提交的數(shù)據(jù)綁定在url中,使用querystring.parse()方法解析url的query屬性便可以得到GET請(qǐng)求提交的數(shù)據(jù)
POST請(qǐng)求提交的數(shù)據(jù)在HTTP的Body中,服務(wù)器接收到的是數(shù)據(jù)流(因?yàn)?b>POST請(qǐng)求提交的數(shù)據(jù)量較大,需要從緩沖區(qū)區(qū)讀取chunk)
利用request對(duì)象的data事件,觸發(fā)回調(diào)函數(shù)接收所有提交的數(shù)據(jù)??梢詫⑵淦唇拥揭粋€(gè)字符串上
接收完所有數(shù)據(jù)后觸發(fā)end事件,此時(shí)才可以使用querystring.parse()解析接收到的所有數(shù)據(jù)
var http = require("http"); var url = require("url"); var fs = require("fs"); var querystring = require("querystring"); var server = http.createServer(); var htmlDir = __dirname + "/html/"; // 使用fs讀取html目錄下的文件 server.on("request", function (req, res) { var urlStr = url.parse(req.url); switch(urlStr.pathname) { case "/": // 首頁(yè) sendData(htmlDir + "/index.html", req, res); break; case "/users": // 用戶(hù)頁(yè) sendData(htmlDir + "/user.html", req, res); break; // 增加登錄頁(yè)面的路由 case "/login": // 用戶(hù)頁(yè) sendData(htmlDir + "/login.html", req, res); break; // 增加登錄頁(yè)面提交數(shù)據(jù)的處理 case "/login/check": // 用戶(hù)頁(yè) if(req.method.toUpperCase() === "GET") { console.log(querystring.parse(urlStr.query)); // 使用querystring.parse()將傳遞的數(shù)據(jù)解析為一個(gè)對(duì)象 } if(req.method.toUpperCase() === "POST") { var str = ""; // 用來(lái)接收POST傳遞來(lái)的數(shù)據(jù) req.on("data", function (chunk) { str += chunk; }) req.on("end", function () { console.log(querystring.parse(str)); }) } break; default : // 不存在 sendData(htmlDir + "/404.html", req, res); break; } }); // 每次請(qǐng)求都讀取靜態(tài)頁(yè)面,再輸出。 fs.readFile()方法封裝了fs.open()、fs.read()和fs.close()方法 function sendData(file, req, res) { fs.readFile(file, function (err, data) { if(err) { res.writeHeader(404, "Not Found", {"Content-Type": "text/html"}); res.end("Not Found"); } else { res.writeHeader(200, "OK", {"Content-Type": "text/html"}); res.end(data); } }); } server.listen(8080, "localhost");常識(shí)
http模塊的服務(wù)器默認(rèn)返回的數(shù)據(jù)類(lèi)型是text/html
http模塊中的http.STATUS_CODES屬性包含所有的狀態(tài)碼及其描述信息
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/86900.html
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類(lèi)中文書(shū)籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開(kāi)發(fā)者開(kāi)始使用開(kāi)發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒(méi)用過(guò)Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車(chē)的還坐過(guò)站了。大家可以很...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類(lèi)中文書(shū)籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開(kāi)發(fā)者開(kāi)始使用開(kāi)發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒(méi)用過(guò)Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車(chē)的還坐過(guò)站了。大家可以很...
摘要:的網(wǎng)站仍然使用有漏洞庫(kù)上周發(fā)布了開(kāi)源社區(qū)安全現(xiàn)狀報(bào)告,發(fā)現(xiàn)隨著開(kāi)源社區(qū)的日漸活躍,開(kāi)源代碼中包含的安全漏洞以及影響的范圍也在不斷擴(kuò)大。與應(yīng)用安全是流行的服務(wù)端框架,本文即是介紹如何使用以及其他的框架來(lái)增強(qiáng)應(yīng)用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清單專(zhuān)注...
摘要:從社區(qū)和過(guò)往的經(jīng)驗(yàn)而言異步編程的難題已經(jīng)基本解決無(wú)論是通過(guò)事件還是通過(guò)模式或者流程控制庫(kù)。本章主要介紹了主流的幾種異步編程解決方案這是目前中主要使用的方案。最后因?yàn)槿藗兛偸橇?xí)慣性地以線性的方式進(jìn)行思考以致異步編程相對(duì)較為難以掌握。 前言 如果你想要深入學(xué)習(xí)Node,那你不能錯(cuò)過(guò)《深入淺出Node.js》這本書(shū),它從不同的視角介紹了 Node 內(nèi)在的特點(diǎn)和結(jié)構(gòu)。由首章Node 介紹為索引...
摘要:這些特性不僅帶來(lái)了大的性能提升,還減少多線程程序設(shè)計(jì)的復(fù)雜性,進(jìn)而提高了開(kāi)發(fā)效率。由公司建立的云計(jì)算平臺(tái)率先支持了。 前言 本文章主要寫(xiě)給那些想了解node語(yǔ)言的開(kāi)發(fā),我的目標(biāo)希望大家通過(guò)閱讀本篇文章能夠簡(jiǎn)單使用node進(jìn)行開(kāi)發(fā),以及了解一些事件驅(qū)動(dòng)的異步編程風(fēng)格,主要分node的背景,安裝配置,模塊創(chuàng)建引用等幾個(gè)方面描述 建議大家在閱讀本篇文章途中 可以親自嘗試一下我所帶來(lái)的小例子,...
閱讀 4184·2021-10-09 09:43
閱讀 3028·2021-10-08 10:05
閱讀 2903·2021-09-08 10:44
閱讀 1016·2019-08-30 15:52
閱讀 2975·2019-08-26 17:01
閱讀 3167·2019-08-26 13:54
閱讀 1805·2019-08-26 10:48
閱讀 964·2019-08-23 14:41