简单的服务器搭载
先把js文件代码拷贝下:
var http = require('http') //这里用node.js的一个内置模块叫http。
//用require去加载这个模块。这个模块就是个对象平台,提供了方法。
http.createServer(function(req,res){
,,,,,,,,,,,,,,
}) //创建服务器,这里有个回调,server函数内部实际上就是个异步的过程,
//内部会创建一个服务器,创建好之后,它会把里面的function的那个函数作为对应的参数来处理我们的请求。
//换句话说,创建好服务器后,当我通过浏览器访问这个服务器时,
//请求底层会被封装成一个对象,对象就是这里的req参数,请求信息都在这个对象里。
//通过req获取用户相关信息,IP,域名,访问信息,,,
//res服务器返回给浏览器的信息,这么一个对象。
例子:
var http =require('http')
var server = http.createServer(function(req,res){
res.write('hello world') //发给浏览器的http内容
res.end() //结束了
})
server.listen(9000) //创建这个服务器后,用.listen这个方法去启动这个服务器,去监听9000这个端口。
如何去运行它?打开终端,当前目录下,输入node 文件名启动。启动后发现页面进入空白地方,输入也没用了。
这时候怎么办?直接在浏览器输入loccalhost:9000访问。如图
这时候看到hello world了。那localhost是什么?它是浏览器的一个host的配置,当你去请求一个域名,中间发生了什么,其中有一步就是通过你的域名去搜索IP地址的这个过程,因为localhost在我们本地做了设置,对应的是127.0.0.1,也就是我本机的IP地址,所以这个请求到了我的本机,然后到了我本机服务器上的9000这个端口了。
这个时候,就相当于这个请求到达我们刚刚启动的服务器了。这个服务器里面,就会进入页面的逻辑,进入到那个回调的函数里,然后再在回调函数里加一条:
var http =require('http')
var server = http.createServer(function(req,res){
console.log(req)
res.write('hello world')
res.end()
})
server.listen(9000)
这时候,关掉终端,再重新来一次,这时候看到终端出现了很多很多的信息,如图这些都是req对象的信息。这里提醒下,代码里仍然可以用console.log(),结果展示在终端。
比如:
var http =require('http')
http.createServer(function(req,res){
console.log('hellojirengu')
res.write('hello world')
res.end()
})
如图现在我们就写了一个简单的服务器了。res.write()是把数据放到响应体里了,当成内容去展示了。响应体就是html文件数据内容。
这就是网站后台的基本逻辑:不管多么复杂,本质都是这样的,一个请求到了服务器,服务器接收然后处理,再发给浏览器,浏览器处理。那为什么不同的URL打开不同的页面?到了服务器里,根据不同的URL执行不同的逻辑,进行不同的操作,然后返回不同的数据。
假设我这个机器想运行多个网站怎么办呢?
报错说9000端口被用了,不能开启。只能关掉了。
细化扩展
设置响应头
通过res.setHeader()设置。
var http= require('http')
var server = http.createServer(function(req,res){
console.log('hahaha')
res.setHeader('content-type','text/plain;charset=gbk')
//告诉浏览器,返回的数据,你当成字符串就可以了,用gbk去解码。
//这个解码方式权重更高,因为这时候html文件还没解析到里面的charset的设置呢。
res.write('hello world')
res.end()
})
server.listen(9000)
响应头内容:如图Response Header内容就是,可以设置很多东西,这里多了一个content-type。
这时候,把res.write()的内容改一下
var http =require('http')
var server = http.createServer(function(req,res){
res.setHeader('content-type','text/plain;charset=gbk')
res.write('<h1>haha</h1>')
console.log('hellojirengu')
res.end()
})
server.listen(9000)
如图content-type='text/plain'就是告诉浏览器,收到数据后当成字符串就行了。
var http =require('http')
var server = http.createServer(function(req,res){
res.setHeader('content-type','text/html;charset=gbk')
res.write('<h1>haha</h1>')
console.log('hellojirengu')
res.end()
})
server.listen(9000)
再试试,如图这就是http协议中的响应头的作用,告诉浏览器发送的响应体数据是什么,怎么处理。同理,如果是CSS就当成css去解析。如图
charset=gbk有什么用?这里没中文,改一下:
var http =require('http')
var server = http.createServer(function(req,res){
res.setHeader('content-type','text/html;charset=gbk')
res.write('<h1>哈哈</h1>')
console.log('hellojirengu')
res.end()
})
server.listen(9000)
//这时候浏览器被服务器通知用gbk解码,所以乱码了。
如图改成charset=utf-8,就如图
所以如果打开网页出现乱码,或者就是算html中meat没有设置,也可以在服务器响应层面去设置的。
这里要明白了,ajax发的请求是请求,毕竟是请求,服务器也不是人,不智能,服务器的响应也是独立的,不是必须要严格符合请求的,而是尽可能地揣测请求。
var path = require('path')
var fs = require('fs')
var url = require('url')
var router = {
'/getData': function(req, res){
var pathObj = url.parse(req.url, true)
var page = pathObj.query.page
var result
if(page == 1){
result = [1,2,3]
}
if(page == 2){
result = [4,5,6]
}
res.write(JSON.stringify(result))
res.end()
},
'/hello': function(req, res){
res.end('hello world')
}
}
再深究一下:
var http =require('http')
var server = http.createServer(function(req,res){
setTimeout(function(){
res.setHeader('content-type','text/html;charset=utf-8')
res.writeHead(200,'haha')
res.write('<html><head><meta charset="gbk" /></head>')
res.write('<body>')
res.write('<h1>哈哈<h1>')
res.write('</body>')
res.write('</html>')
res.end()
},2000)
})
console.log('open http://localhost:8080 ')
server.listen(8080)
运行一下,如图查看一下,如图
网页源代码
通过res.write()的方式写的。只有end的时候,才会结束传输。所以最后看到了全部信息。
那 res.writeHead(200,'haha')有什么意思呢?如图
网页也打开了,事实上是运行没错误,但是出现了404,就报告用户错了,因为404的出现会触发一系列的后续事件,比如报错,颜色红色等。同理,503也会如此,所以,以后设置时,尽量遵循规则设定,以免歧义误导。
为什么没有乱码?因为浏览器先听服务器的解码方式去解码,响应头的数据就是解析依据,响应体就是数据来源,一堆字符串。如果响应头没设置,就再从html中找。
到这里就是把服务器基本原理介绍了,但是这个服务器太简陋了,下面讲真正有普适意义的服务器。
静态服务器
有个点是可以向服务器要html文件和外部加载的文件资源。
换句话说,我们把代码放到一个文件夹里,然后把网站部署到远程的机器上,然后通过终端执行node 服务器文件,开启这个服务器,那网站内容就可以访问了。那他如何访问到的?且看一看!
server.js代码:
var http = require('http') //又多了几个模块
var path = require('path') //处理URL的模块,文件路径的写法在windows或者linux上不一样,会自动识别
var fs = require('fs') //读写文件的,都数据,写数据
var url = require('url') //自动解析URL,并得到信息,相当于在控制台用location,不用再用正则去提取。
function staticRoot(staticPath, req, res){
var pathObj = url.parse(req.url, true)
/*
if(pathObj.pathname === '/'){
pathObj.pathname += 'index.html'
}
*/
var filePath = path.join(staticPath, pathObj.pathname)
var fileContent = fs.readFileSync(filePath,'binary')
res.write(fileContent, 'binary')
res.end()
/*
fs.readFile(filePath, 'binary', function(err, fileContent){
if(err){
console.log('404')
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
}else{
console.log('ok')
res.write(fileContent, 'binary')
res.end()
}
})
*/
}
//首先看这里是创建服务器的,再侦听8080端口。
var server = http.createServer(function(req, res){
staticRoot(path.join(__dirname, 'static'), req, res)
})
//当请求到来后,进入了里面的回调函数,后面一堆是处理请求,写了个staticRoot函数,函数功能就是把一个路径当成静态文件路径,然后再把req,res传进去,再把路径名传进去。
//__dirname是nodejs里面的一个内置变量,直接可用,代表当前的server.js文件,通过方法得到step1的绝对路径。
//'static'指的就是图里面的那个static文件夹。方法得到static的路径。
//两个路径作用后生成一个static的绝对路径。为什么不直接写绝对路径,可能我的文件过几天会改变位置。再一个,代码在各种系统里通用。
server.listen(8080)
console.log('visit http://localhost:8080' )
这个静态服务器如何实现的?
比如说用户访问localhost:8080/index.html的时候,如何让用户看到这个static里面的文件呢?这个请求因为localhost:8080肯定是到了我们这个服务器了。服务器收到请求后,进入了。
var server = http.createServer(function(req, res){
staticRoot(path.join(__dirname, 'static'), req, res)
})
server.listen(8080)这个函数里面,然后该怎么办呢?
是不是通过req得到当前的URL?对吧。得到URL,就可以得到后面的这个后缀:/index.html,只要在本地读取到对应的static下面找到这个文件,把文件内容读出来,读出来之后当成字符串发给浏览器。告诉浏览器,这是html,浏览器就当成html解析,解析后,看到了加载css,js,图片的路径,就会重新组装新的URL,发给服务器,服务器再来一遍,把文件路径确定,读取,再发送。
把文件放到这个文件夹下,通过URL就能访问到,这就是静态服务器。
所以说,关键就是服务器的文件位置,还有html文件的位置了。服务器有什么功能,自己就要去实现什么功能。
还有一些其他的懒人版的成品服务器,就无所谓啦。
测试一下,运行代码是:
var http = require('http')
var path = require('path')
var fs = require('fs')
var url = require('url')
function staticRoot(staticPath, req, res){
console.log(staticPath)
console.log(req.url)
var pathObj = url.parse(req.url, true)
console.log(pathObj) //看下面的截图结果。
var filePath = path.join(staticPath, pathObj.pathname)
//静态路径到了static了,现在再加上这个pathname,得到了请求文件的绝对路径了。然后用下面的fs方法读取。
/* var fileContent = fs.readFileSync(filePath,'binary')
res.write(fileContent, 'binary')
res.end()
*/ //readFileSync同步读取的方法,读完文件得到 fileContent这个东西。再写出去。
fs.readFile(filePath, 'binary', function(err, fileContent){
if(err){ //这个是readFile异步读取,'binary'是二进制方式读取,
//有时候读的不光是字符串,对于图片,文件也希望服务器支持,换成二进制就行了。
console.log('404') //读出错了。
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
}else{
console.log('ok')
res.writeHead(200,'ok')
res.write(fileContent, 'binary') //读到的信息二进制发过去。
res.end() //这里有个疑问,没有给浏览器发送数据解析的标准,没有设置content-type啊。
//这里因为文件后缀index.html会被浏览器辨识,有一定的约定了,当成html文件。a.css也是一样的,虽然响应体里,发请求时,后缀是.css,自动认为是css去解析,同理图片也是一样的。
}
})
}
var server = http.createServer(function(req, res){
staticRoot(path.join(__dirname, 'static'), req, res)
})
server.listen(8080)
console.log('visit http://localhost:8080' )
终端console.log()结果,如图得到了那个绝对位置了。有了这个绝对路径才可以读文件啊。
图里也知道了req.url=/index.html。得到了它,就进行解析,
同理,第三个是req.url=/img/logo.png,,,
这里的pathname是最不会出错的,要它就可以了,判断路径时url.parse这个对象很重要。这里再加一段代码:
if(pathObj.pathname === '/'){
pathObj.pathname += 'index.html'
} //如果pathname=/,就表示,这时候的pathname自己加了下,变成/index.html了,
//如果这时候访问http://localhost:8080/等同于后面加了index.html,直接可访问到文件。
//也就是端口的默认文件。
这是服务器找不到文件的图总结一下吧,搭建服务器,首先是创建,参数有三个,一个是路径,这里指的是请求文件的绝对路径;
一个是请求,请求的一些属性可以帮助得到文件路径;
一个是响应,响应重在反馈,重在设置,设置内容的类型,解码方式,进程的反馈,写内容。
而浏览器只是发请求那个对象和接收数据解析,服务器是接收请求,处理,并找资源,并按设置把响应体和响应头发过去。通过URL的域名定位服务器,通过端口定位。
服务器通过路径得到文件位置。
最简单的逻辑,当然容易挂,不健壮,代码如下:
var http = requirt('http')
var fs = requirt('fs')
var server =http.createServer(function(req,res){
var fileContent = fs.readFileSync(__dirname +'/static' + req.url,'binary')
//这是已经知道文件间的相互位置,干的。__dirname直接得server.js的绝对路径,加那两个就得到了嘛。
res.write(fileContent,'binary')
res.end()
})
server.listen(8080)
console.log('visit http://localhost:8080')
下面就防止服务器崩了的。
var http = requirt('http')
var fs = requirt('fs')
var server =http.createServer(function(req,res){
try{
var fileContent = fs.readFileSync(__dirname +'/static' + req.url,'binary')
res.write(fileContent,'binary')
}catch(e){
res.writeHead(404,'not found')
}
res.end()
})
server.listen(8080)
console.log('visit http://localhost:8080')