内置模块-Http开启web服务器
服务器相关概念
服务器与客户端
服务器
提供网络服务的一台机器,通过在自己的电脑上安装特殊的软件(或者是运行某段特殊的代码)来提供服务
简单来说:服务器 = 电脑 + 能给其它电脑提供服务的软件
客户端与服务器
提供服务的是服务器,享受服务的是客户端
服务器的类型
根据服务不同,服务器的类型也不同,也就是提供服务的软件也不同
web服务器(重点学习)
安装apache/tomcat/iis或者在nodejs环境写代码来提供:图片/视频/音频浏览/新闻数据浏览等服务的服务器
FTP服务器
安装serv-U软件,为其它电脑提供文件下载,共享服务
数据库服务器
安装mysql软件,为其它电脑提供数据库服务
web服务器
用户通过浏览器来享受web服务器提供的图片,视频,音频等网页内容浏览的服务
用户用url地址来访问某个web服务器上的资源
浏览器端发起请求,web服务器收到请求后,响应这个请求,并将处理结果返回给浏览器
浏览器端与web服务器是通过http(或者是https)协议来进行请求和响应的
IP地址
全称:Internet Protocol Address
作用:标识一个网络设备(计算机、手机、电视)在某一个具体的网络当中的地址,要访问某个电脑上的资源,先要找到它的ip
在同一个网络中,计算机的IP是不允许相同的,都是唯一的
IP分类:IPV4(互联网协议第4版)、 IPV6(互联网协议第6版)
IPV4格式:[0-255].[0-255].[0-255].[0-255] 即为四个 0-255 的数字组成
例如:127.0.0.1(本机访问) 或 192.168.106.2(局域网访问) 或 220.181.38.149(外网访问)
IPV6格式:X:X:X:X:X:X:X:X,每个X 以十六进制表示(了解)
例如:FF01:0:0:0:0:0:0:1101 → FF01::1101,可以把连续的一段0压缩为“::”
域名
域名:ip地址的别名
由于ip地址不好记忆,我所以给它们取个好记的别名
127.0.0.1 的别名为 localhost
系统自动解析的,不需要做额外的配置
220.181.38.149的别名为 www.baidu.com
需要域名解析系统把域名翻译成IP地址,需要额外购买和配置
端口
理解:如果理解IP地址(一台服务器)是一栋大商场,端口就是商场中的商铺的编号
一个网络设备可以有65536个端口,范围是从[0,65535])
不同的端口被不同的软件占用,以提供不同的服务
服务器要提供服务必须要通过指定的端口
客户端与服务器都需要通过特定端口要进行通信(http://157.122.54.189:9092) 端口是可以编程分配
有一些端口号是被预定了的
- http: 80
- https:443
- mysql:3306
HTTP协议
协议:制定客户端与服务器之间的通讯规则,不同的协议的作用也不同,我们主要了解HTTP协议 http协议
定义:HTTP(HyperText Transfer Protocol) 超文本传输协议,浏览器与web服务器都要遵守的协议 HTTP 协议中明确规定了请求数据和响应数据的格式(报文)
浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)
服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)
实现一个Web服务器
用http 模块写一个简单的web服务器
HTTP在线文档 nodejs.org/dist/latest…
引入http核心模块
使用createServer来创建服务
使用listen来启动服务,端口为8001(端口可以修改 0 - 65535)
在浏览器输入http://127.0.0.1:8001回车即可看到服务器响应回来的信息:OK
也可以通过ipconfig查看你的本机ip,通过 http://局域网ip:8001回车访问
// 创建第一个web服务器
// 1、导入http模块
const http = require('http')
// 重点注意两个参数
// req request 请求(对象)
// res response 响应(对象)
// 2、创建一个服务(类似后端的事件)
const server = http.createServer((req, res) => {
// req.method 获取用户请求方式
// req.url 获取用户请求地址
console.log('接受到了客户的请求', req.method, req.url);
res.end('OKlin')
})
// 3、 监听8001端口并启动web服务器等待客户端请求
server.listen(8002, () => {
console.log('服务器启动成功提示');
})
根据不同的url响应不同的内容
const http = require('http')
const server = http.createServer((req, res) => {
console.log('接受到了客户的请求', req.method, req.url);
if (req.url === '/') {
res.end('Hello Index') // http://127.0.0.1:8001
} else if (req.url === '/joke') {
// 服务器告诉浏览器,响应的内容类型为: 文本,编码格式为 utf8
res.setHeader('content-type', 'text/html;charset=utf8')
res.end('哈哈哈~') // http://127.0.0.1:8001/joke
} else {
// 📤res 响应对象
res.end('404')
}
// 🚨 多个 res.end 被调用会导致服务器崩溃
// res.end('404')
})
// 3. 开启监听
server.listen(8001, () => {
console.log('服务器启动成功提示')
})
工作原理
使用http模块在本机上创建一个Web服务器,它来接收浏览器的请求,并给出响应。
Http模块创建Web服务器代码解析
引入核心模块require('http'),得到的http是一个对象
http.createServer方法创建一个http服务
createServer方法参数是一个回调函数:当有http请求进来时,它会自动被调用,请求一次,它就被调用一次
req参数:客户端的请求相关数据
res参数:设置对本次请求的响应相关数据
server.listen() 用来监听端口
如果监听成功,则回调函数会执行一次。
如果不成功(例如端口被占用),会报错。
req.url
通过 req.url来获取当前请求的url路径
req.url在哪儿?
req.url具体用法和效果
代码
不同的请求url通过req.url获取的结果
res.end()设置响应体
语法:res.end(响应的数据)
end()只能传入buffer或者是String类型的数据
作用:设置响应体并结束本次请求
用法:在createServer的回调函数中使用
注意:一次请求只能有一个res.end()响应,多个以第一个响应的数据为准,同时服务器报错终止
res.setHeader()设置响应头解决中文乱码
作用:设置响应头信息,控制浏览器的一些行为
语法:res.setHeader(响应头,响应值),两个参数的具体值都是http协议规定的
用法:在createServer的回调函数中使用
注意:
res.setHeader()在res.end()之前才有效
res.setHeader()可以设置多次
应用举例:解决响应中文字符在浏览器显示成乱码问题
res.setHeader(“Content-Type”,”text/html;charset=utf8”):
res.statusCode设置状态码
场景:浏览器输入了一个不存在的url,则服务器返回404状态码
语法:res.statusCode = 状态码,状态码是http协议规定的
状态码: 500 (服务器异常) 404(资源找不到)
注意:res.statusCode只有在res.end()前执行才有效
content-type作用
在http协议中,content-type用来告诉对方本次传输的数据的类型是什么
在请求头中设置content-type来告诉服务器,本次请求携带的数据是什么类型的
在响应头中设置content-type来告诉浏览器,本次返回的数据是什么类型的
res.setHeader方法可以设置content-type这个响应头,浏览器根据不同类型做出不同解析
※ 请求头和响应头都可以设置content-type
常见的几种文件类型及content-type
常见的几种文件类型及content-type
- .html:res.setHeader('content-type', 'text/html;charset=utf8')
- .css:res.setHeader('content-type', 'text/css;charset=utf8')
- .js:res.setHeader('content-type', 'application/javascript')
- .png:res.setHeader('content-type', 'image/png')
- json数据:res.setHeader('content-type', 'application/json;charset=utf-8')
※ 如果读取.html的文件内容,但是content-type设置为了text/css则浏览器将不会当作是html页面来渲染了
练习案例 随机笑话
const http = require('http')
const server = http.createServer((req, res) => {
console.log('接受到了客户的请求', req.method, req.url);
if (req.url === '/joke') {
const arr = ['1、在我还在上大学那会,有一天去系办找辅导员,正好在楼梯遇到一个平日很装的同学,我上楼同学下楼,相遇的刹那,同学一仰头,很是高傲的瞄了我一眼,嘴角划过一丝不屑的笑,保持这种姿态直接一步跨出,然后我羞羞的伸出了脚,然后整栋楼传来嗷的一声……', '2、一男子应聘,面试官问在上一个公司离职的原因,男子答:公司搬了新大楼,没有告诉我地址', '3、 本人20多岁妹纸一枚,从小特别怕痒一次去一个老中医那推拿,单独房间他是五六十岁大叔级别我往床上一趴,他推一下我嗷一嗓子,推一下我嗷一嗓子半分钟后他忍不住了说,不收你钱了你走吧,我是一个要名誉的人……', '4、 元旦去看电影。看得好好的,突然屏幕黑了,上来一个主持人,拿着话筒,说:“下面哪个大哥带别人媳妇来的?赶紧跑吧,人家老公来抓了!”然后我一回头,就没有几个人了……', '5、宫廷玉液酒,一百八一杯,这酒怎么样啊?听我给你吹。一杯你开胃,(我喊了一声美)二杯你肾不亏,(哈哈 还是美),三杯五杯进了肚,保证你的小脸啊,是白里透着红啊,红里透着黑', '6、夜空一颗流星划过,我连忙许了心愿,希望你能变漂亮些,谁知刚许完心愿,流星“嗖”地返回来,对我说:大哥!诚心为难我是不是?!', '7、一天阿呆突然发现他有大姨,二姨,四姨,却没有三姨。于是就去问他爸:为什么我没有三姨?难道三姨在小的时候就死了?他爸怒道:你三姨就是你妈!', '8、某人养一猪,烦,弃之,然猪知归路,数弃无功。一日,其驾车转了很多弯弃猪,深夜致电家人,问:“猪归否?”答曰:“已归!”其怒吼:“让它接电话,老子迷路了!"', '9、看哪个银行缩写最牛:中国建设CBC(存不存),中国银行BC(不存),中国农业银行ABC(啊不存),中国工商银行ICBC(爱存不存),民生银行CMSB(存吗傻B)。', '10、艺术家问画廊老板是否有人买他的画。老板:“有个人问我你死后这些画会增值多少,我告诉他后他买了一幅画。不过他说他是你的医生。”', '11、胡萝卜见客户,恭敬地递上名片,客户看名片问:你怎么叫高丽参啦?胡萝卜小腰一挺,“人家哈韩了嘛!”']
const index = Math.round(Math.random() * arr.length-1)
// 解析字符编码 中文乱码
res.setHeader('content-type', 'text/html;charset=utf8')
res.end(`${arr[index]}`)
} else {
// 📤res 响应对象
res.end('404')
}
})
// 3. 开启监听
server.listen(8001, () => {
console.log('服务器启动成功提示')
})
Web服务器处理接口响应
接口请求方式
发送接口请求的类型
- get:在地址栏中直接访问这个url就是get方式。
- post:通过表单提交,可以设置$.ajax的type为post
- delete
- put web服务器通过req.method获取当前请求的类型
接口的各种表现形式
- get请求不带参数的接口: http://127.0.0.1:8003/getHero
- get请求带参数的接口: http://127.0.0.1:8003/getHero?heroName=后羿
- post请求接口 http://127.0.0.1:8003/addHero (参数在请求报文体中传输)
使用软件测试接口请求方式
const http = require('http')
// 创建服务
const server = http.createServer((req, res) => {
// 解构 请求方式 method 和请求地址 url
const { method, url} = req
// 防止中文乱码
res.setHeader('Content-Type','text/html;charset=utf8')
// 通过分支,区别不同的客户端请求 响应不同结果
if(method === 'GET' && url === '/meber/car') {
// 如果是 get /meber/car
res.end('获取购物车列表')
}else if (method === 'POST' && url === '/meber/car' ){
// 如果是 POST /meber/car
res.end('加入购物车(新增)')
}else if (method === 'DELETE' && url === '/meber/car' ){
// 如果是 DELETE /meber/car
res.end('删除购物车商品')
}else {
// 以上都不是 兜底响应404 因为服务器没响应 浏览器会一直转圈圈等待
res.statusCode = 404
res.end('404')
}
res.statusCode = 404
})
// 启动服务(监听)
server.listen(8000, () => {
console.log('服务器启动成功');
})