上周在这篇文章 有一个网络问题请教你 中,我向大家请教了个问题,意思就是如何获取 HTTP 请求「未经过解析的数据」。得到了几位同学的解答,再此感谢你们的帮助,互帮互助一直到是小课的「文化」。我们先一起回顾一下他们的回答:
@满天星:http 基于tcp。所以请求和响应就是数据。通过wireshark可以清楚的看到几包数据构成一个http请求或者响应。请求的话,两个换行就代表结束了。响应的话,一般都有contentlenth字段。http 1.0协议比较简单,模拟也比较简单。可以去github上找两个简单的server/client的例子,很简单就可以看到数据了。
@L,@conan 他俩表示使用抓包软件 Wireshark 就可以看到。
Charles 抓包软件是可以抓取到请求和响应的数据,但是我不太确定 Charles 是不是对原始数据进行了解析,会导致我看到的数据不是原始数据,后来经过证实在 Raw 下的数据是未解析的,它只不过是把二进制数据转换成了字符串。
后来我意外发现其实非常简单就可以看到请求数据,还记得在 第4天:数据传输之 TCP ,聊天室实践(含视频)中我们讲过 TCP 协议吗?HTTP 既然是基于 TCP 的,那么 TCP 传过来的数据便是 HTTP 请求的原始数据,我们验证一下,先创建一个 TCP 服务:
let net = require('net');
// 创建 TCP 服务
let server = new net.Server();
// 端口号
const port = 8686;
let Log = function(msg) {
console.log(msg);
};
// 监听 connection 事件
server.on("connection", function (socket) {
// 当收到客户断消息会响应这个事件
socket.on('data', function(data) {
// data 是二进制数据
Log(data);
});
});
// 监听某个端口
server.listen(port, function() {
let address = server.address();
Log("Server run on: http://127.0.0.1:" + address.port);
});
通过 node tcp_server2.js 启动 TCP 服务,然后在浏览器输入:
http://127.0.0.1:8686/suyan/fe?name=lefex
16 行代码打印了 TCP 接收到的数据 Log(data),16进制数据;
把上面的而16进制数据转换成字符串,把 Log(data) 换成 Log(data.toString());在浏览器中同样输入 http://127.0.0.1:8686/suyan/fe?name=lefex ,可以看到浏览器发过来的数据。
这就是请求报文,通过自己动手写的 TCP 服务直接获取请求数据,更具有说服力。还记得我们讲过请求报文的格式吗?第 8 天:弄懂 HTTP 请求报文。
总结
通过本文,你能够明白 HTTP 请求是通过 TCP 传输数据,传输的就是「有规则的字符串」,直接解析就好了,然后把响应给客户端返回,就搞定了。代码可以在这里找到:https://github.com/lefex/FE 。大家加油。
推荐阅读: