文章共1862字,阅读大概需要13分钟。边敲边学大约需要42分钟。
(欢迎参与文章最后的投票)
使用Node进行网络开发
用户在浏览器中输入网址 --> 获得网页的过程经历了几个步骤:
通过浏览器发送一个请求到服务器(期间经历的DNS解析、TCP3次握手连接)
服务器分析、处理用户的请求,并生产请求的内容,然后发送给浏览器
浏览器解析服务发送回的数据,生产网页
服务器
在HTTP协议中的服务器指:监听客户端的请求,并且根据请求的内容进行相应处理,返回响应给客户端。
Node中可以利用http模块进行Web服务器的搭建。
http模块
http模块不是Node的核心模块,需要利用require()加载
使用http.createServer()方法创建一个http服务器,返回一个http服务器对象
利用服务器对象进行开发
接收的回调函数是监听到客户端请求时的回调函数
3. server.listen()方法可以开启Web服务,监听某台主机的某个端口
参数是(port, hostname, backlog, callback)
port是监听主机的端口号;hostname是监听主机的IP地址;callback是服务器成功开启后的回调函数(开启服务器后,再连接数据库)
// 搭建 一个HTTP服务器,用于处理用户发送的http请求
// http模块不是核心模块,需要require()导入
var http = require('http');
// http模块的createServer()方法可以返回一个标准http服务器对象
// 通过服务器对象来进行开发
// callback是监听到客户端连接的回调函数
var server = http.createServer(callback);
// 服务器监听某个网卡上的某个端口,开启服务
// listen(port, hostname, backlog, callback)
// port是监听的端口,hostname是监听主机的ip地址,callback是服务器开启成功后的回调函数
// 服务器开启失败时触发error事件
server.on('error', function (err) {
console.log(err);
})
// listening事件在服务器开启成功时触发
server.on('listening', function () {
console.log('listening...8080');
})
// 监听来自客户端的请求事件,在接收到请求时触发
server.on('request', function () {
console.log("there is a request");
})
server.listen(8080, 'localhost');
主要的事件
服务器开启失败的事件error的监听:server.on('errro', function(err) {})
服务器开启成功的事件listening的监听:server.on('listening', function(err) {}),可以写在server.listen()方法的回调函数中
服务器接收到请求的事件request的监听:server.on('request', function(err, req, res) {}),可以写在http.createServer()方法的回调函数中
参数对象
request事件接收两个参数:
write(chunk, [encoding]):发送一个数据库到响应的正文(网页的内容数据)中,需要在发送完成后调用res.end()方法
end(chunk, [encoding], [callback]):在通过write()方法发送完所有正文和头信息后,需要res.end()告诉服务器数据全部发送完成。每个响应都必须调用res.end()方法,并且在最后调用。
如果指定了 chunk,则它等同于调用 response.write(chunk, encoding) 之后调用 response.end(callback)
writeHeader(statusCode [, statusMessage] [, headers]):写入头信息,在res.write()前调用,并且一次响应中只能调用一次,头信息写在一个对象中
statusCode属性和setHeader()方法可以组合实现writeHeader()的功能
server.on('request', function (req, res) {
console.log("there is a request");
var chunk = '
hello world
';
// Buffer.byteLength(chunk)以字节为单位,告诉浏览器以纯文本解析传回的数据
res.writeHeader(200, 'OK', {'Content-type': 'text/plain', 'Content-length': Buffer.byteLength(chunk)});
res.end(chunk, 'utf-8');
})
url处理
根据用户请求的path返回不同的数据,使用req.url可以获取path信息。
server.on('request', function (req, res) {
console.log(req.url); // req.url获取请求的路径path信息
var urlStr = url.parse(req.url);
switch(urlStr.pathname) {
case '/': // 首页
res.writeHeader(200, 'OK', {'Content-type': 'text/plain'});
res.end('
首页
', 'utf-8');break;
case '/users': // 用户页
res.writeHeader(200, 'OK', {'Content-type': 'text/plain'});
res.end('
用户页
', 'utf-8');break;
default : // 不存在
res.writeHeader(404, 'Not Found', {'Content-type': 'text/plain'});
res.end('
出错
', 'utf-8');break;
}
})
使用fs模块实现行为与表现分离
根据用户不同访问的不同路径,执行不同操作,读取不同页面
server.on('request', function (req, res) {
console.log(req.url);
var urlStr = url.parse(req.url);
switch(urlStr.pathname) {
case '/': // 首页
sendData(htmlDir + '/index.html', req, res); // 请求不同的路径,读取不同的页面返回给客户端
break;
case '/users': // 用户页
sendData(htmlDir + '/user.html', req, res);
break;
default : // 不存在
sendData(htmlDir + '/404.html', req, res);
break;
}
});
// 每次请求都读取静态页面,再输出。 fs.readFile()方法封装了fs.open()、fs.read()和fs.close()方法
// fs.readFile()返回值是原始的buffer对象
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请求提交的数据
通过GET方法传递的数据可以使用url.parse(req.url).query获取到GET请求提交的数据,使用querystring内置模块(无需加载)来解析
GET请求提交的数据绑定在url中,使用querystring.parse()方法解析url的query属性便可以得到GET请求提交的数据
POST请求提交的数据在HTTP的Body中,服务器接收到的是数据流(因为POST请求提交的数据量较大,需要从缓冲区区读取chunk)
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 '/': // 首页
sendData(htmlDir + '/index.html', req, res);
break;
case '/users': // 用户页
sendData(htmlDir + '/user.html', req, res);
break;
// 增加登录页面的路由
case '/login': // 用户页
sendData(htmlDir + '/login.html', req, res);
break;
// 增加登录页面提交数据的处理
case '/login/check': // 用户页
if(req.method.toUpperCase() === 'GET') {
console.log(querystring.parse(urlStr.query)); // 使用querystring.parse()将传递的数据解析为一个对象
}
if(req.method.toUpperCase() === 'POST') {
var str = ''; // 用来接收POST传递来的数据
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;
}
});
// 每次请求都读取静态页面,再输出。 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');
常识
转自: https://segmentfault.com/a/1190000008648371
作者: Kyxy
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
==========阅读原文==========