第3天:HTTP 之客户端与服务端

从搭建 WebServer 到 Express 框架的使用,我们正在逐步接近HTTP。我们今天的主题是围绕 Node 来创建一个 HTTP 客户端和 Server 端,感受一下不使用第三方框架时如何使用 HTTP。

Node.js 提供了 HTTP 模块,可以直接拿来使用,也可以作为我们学习 HTTP 协议的线索。并实现了 TCP 和 UDP。

很久以前,我比较好奇为什么客户端发出一个请求后,server 端会接收到请求呢?为什么请求需要 ip 地址和端口号呢?端口号是用来干什么的?server 端是如何发出响应的?遇到各种状态码该如何找到问题的原因?为什么抓包软件可以抓取到 HTTP 请求?HTTPS 是如何实现的?HTTP 和 TCP 有什么关系呢?socket 起到了什么作用?这些问题,面试的时候被问到的时候,我会给出一个「连我自己都不知道对错的答案」,因为网上就是这么说的,我没有实际验证过,也没看过 HTTP 是如何实现的,而 Node 对 HTTP 模块的实现无疑是为我们这一阶段的学习提供了很多有价值的资料。这一阶段我们要学习这些内容,从原理上来搞懂 HTTP。时间长,任务重,贵在坚持。

使用 Node 中的 HTTP 模块不仅可以实现一个 HTTP server,而且可以作为客户端发起 HTTP 请求,也就是使用 Node 可以同时实现客户端与 server 端,这就可以替换掉上节课程 第2天:server 的接口是如何实现的 使用的 iOS 客户端。使用 Node 来创建一个 HTTP Server。

分析一下下面的代码(server.js 文件),在 Node 中首先需要引用 HTTP 模块,然后通过 HTTP 来创建一个 server 对象,通过 server 对象便可以监听它的一系列事件,其中最常用的是 request 事件,它接收到客户端请求事件时就会执行,这时server端会根据请求对象发出的「指令」来做事情。这里,我们只处理了请求 path 为 /api/fe/list 的 request,其它请求一律都走 404。最后需要通过 listen 方法来制定一个端口号。

const http = require('http');// 创建一个 HTTP serverconst server = new http.Server();
/** * request 事件,当客户端发起请求后会响应这个事件 * req:请求对象 * res:响应对象 * */ server.on('request', function(req, res) { let path = req.url; if (path.indexOf('/api/fe/list') == 0) { // 处理请求的 path 为 /api/fe/list res.writeHead(200, { "Content-type" : "application/json" }); let data = { title: "前端小课", des: "内容由素燕公众号发布" }; // 最终数据需要转换成 json 字符串 res.write(JSON.stringify(data)); } else { // 未实现,直接报 404 错误 res.writeHead(404, { "Content-type" : "application/json" }); let data = { code: "404", msg: "not found" }; res.write(JSON.stringify(data)); } res.end();});
// 监听 8888 端口server.listen(8888, function() { console.log('Server run in: http://127.0.0.1:8888');});

通过 node server.js 来启动上面的HTTP 服务:

服务启动后,在浏览器中访问,发现有正常的响应信息:

http://127.0.0.1:8888/api/fe/list

在浏览器中访问,发现响应为 404 的错误:

http://127.0.0.1:8888/

Node 的 HTTP 实现是基于事件的,可以通过 on 方法来监听不同的事件。上面的代码中我们监听了 request 事件,它触发的时机是当客户端发起网络请求后,就会执行这个事件。它会携带请求对象 req 和响应对象 res,req 是用来获取客户端的请求数据,这样 server 可以做出正确的响应。Node 也可以充当客户端来发起网络请求。

下面的代码(client.js)创建一个 HTTP 客户端来发起网络请求,通过 http.request 方法来发起请求,通过 options 来声明请求需要的信息。

const http = require('http');
// 构建 request 对象所需要的参数const options = { // 请求地址 ip host: '127.0.0.1', // 端口号 port: 8888, // 方法 method: 'GET', // 请求的路径 path: '/api/fe/list', protocol: 'http:', // 超时时间设置 1秒 timeout: 1000}
const req = http.request(options, function (res) { console.log(`STATUS: ${res.statusCode}`); console.log(`HEADERS: ${JSON.stringify(res.headers)}`); res.setEncoding('utf8'); // 响应数据 res.on('data', (chunk) => { console.log(`BODY: ${chunk}`); }); // 响应结束 res.on('end', () => { console.log('No more data in response.'); });});
req.on('error', (e) => { console.error(`problem with request: ${e.message}`);}); req.end();

通过 node client.js 执行一下客户端的代码,下面执行了 2 次请求,和在浏览器发起请求结果是一致的。在执行请求的时候需要先执行 server.js 来启动服务,然后在执行 client.js:

上面代码的 demo 可以在 https://github.com/lefex/FE 上下载。

总结

本节内容我们使用 Node 模拟了客户端和 Server 端,我们并没有细讲 HTTP 协议,后续我们会更详细地讲解 HTTP 报文。HTTP 属于应用层协议,客户端与server端需要遵循 HTTP 协议的标准。而负责数据的传输是靠 TCP 进行传输的。下节内容我们学习数据传输相关的内容,TCP、UDP、Socket。大家加油!!!

打卡互动(任选一个):

1.TCP 与 socket 有关系吗?

2. socket 是什么,为了解决什么问题?

3.直接打卡。

推荐阅读:
第1天:一条命令开启一个 WebServer
第2天:server 的接口是如何实现的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值