Node.js入门之http模块和dns模块

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 在nodejs中,http可以说是最核心的模块,借助http模块,可以几行代码就搞定一个超迷你的web server。学好http模块对于后面的web框架express、koa的学习也很有帮助。

http服务分为客户端和服务端。我们先来说说服务端。

服务端

创建HTTP服务器

http.createServer(fn)用来创建http服务器

const http = require("http");

const server = http.createServer((serverReq, serverRes) => {});

当服务器收到客户端的请求后就会进入该方法serverReq是请求对象,serverRes是服务器端响应对象。

启动HTTP服务器

server.listen(port,[host],[backlog],[callback]);用来启动服务器。

  • port 监听的端口号
  • host 监听的地址
  • backlog 指定位于等待队列中的客户端连接数
  • callback 回调函数
server.listen(3000, () => {
  console.log("服务启动啦")
})

关闭HTTP服务器

server.close()用来关闭http服务,并且还可以监听该事件。

const http = require("http");

const server = http.createServer(function (serverReq, serverRes) {
  const url = serverReq.url;
  serverRes.end("您访问的地址是:" + url);
});

server.on("close", () => {
  console.log("服务关闭啦");
});

server.listen(3000, () => {
  console.log("服务器端开始监听!");
  server.close();
});

监听服务器错误

server.on('error', (e)=>{
  console.log(e)
});

设置超时时间

通过server.setTimeout(msecs, callback)设置超时时间,超时后不可再复用已经建立的连接,需要发请求需要重新建立连接。默认超时时间是2分钟。

server.setTimeout(msecs, callback);

通过监听timeout事件来进行超时处理。

server.on('timeout',function(){
  console.log('连接已经超时');
});

服务端请求对象

服务端请求对象req它其实是http.IncomingMessage实例,我们通常会用它来获取headerurl
、参数等信息。

获取请求链接、http版本、请求方法、请求头部

const http = require("http");

const server = http.createServer((req, res) => {
  console.log("1、客户端请求url:" + req.url);
  console.log("2、http版本:" + req.httpVersion);
  console.log("3、http请求方法:" + req.method);
  // 这里使用JSON.stringify是为了方便在控制台查看,实际上是一个对象可以直接使用
  console.log("4、http请求头部" + JSON.stringify(req.headers));

  res.write("hello");
  res.end("world");
});

我们在浏览器键入http://localhost:3000/hello输出如下

image.png

获取get请求参数

既然有请求,那一定会有参数,我们先来说说获取get请求参数。

get请求的参数都会在url里面,我们一般会使用前面学习的url或者querystring模块进行处理。

const http = require("http");
const url = require("url");

const server = http.createServer((req, res) => {
  // 利用前面学习的url模块进行参数处理
  const params = url.parse(req.url, true);
  console.log(params.query);

  res.write("hello");
  res.end("world");
});

我们在浏览器键入http://localhost:3000/hello?name=randy输出如下

image.png

获取post请求参数

我们知道,get请求的参数是在浏览器路径里面,但是post请求的参数是在请求体里面,那这样我们怎么获取到参数呢?

这里就要用到请求对象req的一些事件了。

const http = require("http");

const server = http.createServer((req, res) => {
  let body = "";
  req.on("data", function (thunk) {
    body += thunk;
  });

  req.on("end", function () {
    console.log("post body is: " + body);
    res.end("ok");
  });
});

我们用postman构造一个post请求,http://localhost:3000传递参数name:jack输出如下

image.png

服务端响应对象

服务端响应对象,它其实是http.ServerResponse实例。

当接受到来自客户端的http请求后,用来向客户端返回响应内容,比如状态代码/状态描述信息、响应头部、响应主体。

设置状态代码、状态描述信息

我们可以通过res.statusCoderes.statusMessage来设置状态代码、状态描述信息。

当然你也可以直接使用设置头部方法res.writeHead来设置。相当于是一个简写。

const server = http.createServer((req, res) => {
  
  // 简写 res.writeHead(200, "ok")
  
  res.statusCode = 200;
  res.statusMessage = "ok";
  
  res.write("hello");
  res.end("world");
});

设置响应头

我们使用res.writeHead()res.setHeader() 来实现响应头部的设置。

不过需要注意,就是setHeader只能写在writeHead的前面,不然会报错。也就是说writeHead可以覆盖setHeader,但是反过来不行。

const http = require("http");
const url = require("url");

const server = http.createServer((req, res) => {
  // 设置头部,只能在writeHead的前面,不能在后面。但是writeHead可以覆盖setHeader
  res.setHeader("Content-Type", "text-plain");

  res.writeHead(200, "ok", {
    "Content-Type": "text/html",
  });
  
  res.write("hello");
  res.end("world");
});

获取响应头、删除响应头

既然可以设置响应头,当然也可以获取和删除响应头。通过getHeaderremoveHeader来获取和删除响应头。

const http = require("http");
const url = require("url");

const server = http.createServer((req, res) => {

  // 设置
  res.setHeader("Content-Type", "text-plain");
  // 获取
  console.log(res.getHeader("content-type")); //text-plain
  // 删除
  res.removeHeader("Content-Type");
  
  res.writeHead(200, "ok", {
    "Content-Type": "text/plain",
  });

  res.write("hello");
  res.end("world");
});

设置响应主体

设置响应主体主要用到 res.write() 以及 res.end() 两个方法

response.write(chunk[, encoding][, callback])

  • chunk:响应主体的内容,可以是string,也可以是buffer。当为string时,encoding参数用来指明编码方式。(默认是utf8)
  • encoding:编码方式,默认是 utf8。
  • callback:当响应体flushed时触发。

response.end([data][, encoding][, callback])

掌握了 res.write() 的话,res.end() 就很简单了。res.end() 的用处是告诉nodejs,header、body都给你了,这次响应就到这里吧。简单理解就是传递响应体并结束。

客户端

http服务除了用在服务端,还可以用在客户端。对于客户端主要用来创建http客户端请求。

创建GET请求

下面构造了个GET请求,访问 http://jsonplaceholder.typicode.com/todos/1 ,并将返回的内容打印在控制台。

const http = require("http");

const options = {
  protocol: "http:",
  hostname: "jsonplaceholder.typicode.com/todos/1",
  port: "80",
  path: "/",
  method: "GET",
};

const client = http.request(options, function (req) {
  let data = "";
  req.setEncoding("utf8");
  req.on("data", function (chunk) {
    data += chunk;
  });
  req.on("end", function () {
    console.log(data);
  });
  
  console.log(req.statusCode); // 200
  console.log(req.statusMessage); // ok
});

client.end();

输出如下,可以看到,通过get请求,获取到了返回的内容。

image.png

当然,我们还可以用便捷方法 http.get(options)

http.get("http://jsonplaceholder.typicode.com/todos/1", function (req) {
  let data = "";
  req.setEncoding("utf8");
  req.on("data", function (chunk) {
    data += chunk;
  });
  req.on("end", function () {
    console.log(data);
  });
  
  console.log(req.statusCode); // 200
  console.log(req.statusMessage); // ok
});

创建post请求

下面构造了个POST请求,访问 http://jsonplaceholder.typicode.com/posts ,并将返回的内容打印在控制台。

const options = {
  method: "POST",
  protocol: "http:",
  hostname: "jsonplaceholder.typicode.com",
  port: "80",
  path: "/posts",
  headers: {
    connection: "keep-alive",
    "content-type": "application/json; charset=UTF-8",
  },
};

// 发送给服务端的数据
const postBody = {
  title: "foo",
  body: "bar",
  userId: 1,
};

// 创建客户端请求
const client = http.request(options, function (req) {
  let data = "";
  req.on("data", function (chunk) {
    data += chunk;
  });
  req.on("end", function () {
    console.log(data);
  });
  
  console.log(req.statusCode); // 200
  console.log(req.statusMessage); // ok
});

client.write(JSON.stringify(postBody));
client.end();

输出如下,可以看到,通过post请求,获取到了返回的内容。

image.png

可以发现,服务端、客户端都有req对象,它们其实都是http.IncomingMessage实例。那这两者是一样的吗?其实是有细微差别的。具体如下图

image.png

取消请求

可以使用abort方法来终止本次请求

req.abort();

域名解析

域名解析顾名思义,就是将于域名解析为ip地址。在node中我们可以使用dns模块来实现该功能。

下面我们来说说dns模块两个个常用的方法lookupresolve4

lookup()

比如我们要查询域名 www.qq.com 对应的ip,可以通过 dns.lookup()

const dns = require("dns");

dns.lookup("www.qq.com", function (err, address, family) {
  if (err) throw err;
  console.log("ip地址为: " + address); // 101.91.22.57
});

我们知道,同一个域名,可能对应多个不同的ip。那么,如何获取一个域名对应的多个ip呢?可以这样。

const dns = require('dns');
const options = { all: true };

dns.lookup("www.qq.com", options, function (err, address, family) {
  if (err) throw err;

  console.log("ip地址为: " + JSON.stringify(address)); // [{"address":"101.91.22.57","family":4},{"address":"101.91.42.232","family":4}]
});

resolve4()

上面的例子,我们使用resolve4方法也能实现。

dns.resolve4("www.qq.com", function (err, address) {
  if (err) throw err;
  console.log(JSON.stringify(address)); // ["101.91.22.57","101.91.42.232"]
});

从上面的例子来看,两个方法都可以查询域名的ip列表。那么,它们的区别在什么地方呢?

可能最大的差异就在于,当配置了本地Host时,是否会对查询结果产生影响。

  • dns.lookup():有影响。
  • dns.resolve4():没有影响。

举例,在hosts文件里配置了如下规则。

127.0.0.1 www.qq.com

运行如下对比示例子,就可以看到区别。

const dns = require('dns');

dns.lookup('www.qq.com', function(err, address, family){
    if(err) throw err;
    console.log('配置host后,dns.lokup =>' + address);
});

dns.resolve4('www.qq.com', function(err, address, family){
    if(err) throw err;
    console.log('配置host后,dns.resolve4 =>' + address);
});

输出如下

配置host后,dns.lookup =>127.0.0.1
配置host后,dns.resolve4 =>182.254.34.74

系列文章

Node.js入门之什么是Node.js

Node.js入门之path模块

Node.js入门之fs模块

Node.js入门之url模块和querystring模块

Node.js入门之http模块和dns模块

Node.js入门之process模块、child_process模块、cluster模块

听说你还不会使用Express?

听说你还不会使用Koa?

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!

相关文章
|
1月前
|
缓存 JavaScript 安全
nodejs里面的http模块介绍和使用
综上所述,Node.js的http模块是构建Web服务的基础,其灵活性和强大功能,结合Node.js异步非阻塞的特点,为现代Web应用开发提供了坚实的基础。
101 62
|
1月前
|
缓存 JSON JavaScript
Node.js模块系统
10月更文挑战第4天
36 2
|
29天前
|
JSON 前端开发 JavaScript
前端模块打包器的深度解析
【10月更文挑战第13天】前端模块打包器的深度解析
|
29天前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化
|
1月前
|
JavaScript 应用服务中间件 Apache
Node.js Web 模块
10月更文挑战第7天
29 0
|
1月前
|
JavaScript 网络协议
Node.js 工具模块
10月更文挑战第7天
20 0
|
1月前
|
JavaScript 前端开发 应用服务中间件
Node.js Web 模块
Node.js Web 模块
|
域名解析 Web App开发 存储
HTTP的基础知识和DNS的解析过程
我们都知道现在大部分的B/S 系统。其核心的通讯协议还是 TCP/IP 协议,应用层的话就是HTTP 协议,我们最常的打交到的就是HTTP协议了。所以了解HTTP协议的相关知识显得尤为重要。
1929 0
HTTP的基础知识和DNS的解析过程
|
网络协议 Java uml
Java如何在HTTP请求时做DNS解析?
Java如何在HTTP请求时做DNS解析?
438 0
Java如何在HTTP请求时做DNS解析?
|
网络协议
使用dnspod进行简单的HTTP dns解析(防劫持)
https://www.dnspod.cn/httpdns/guide https://www.dnspod.cn/misc/D%2B免费版本接口说明.pdf 最简单的get接口去请求dnspod提供的ip地址,请求格式为: "http://119.29.29.29/d?dn=apis.baidu.com." 不要遗漏最后的那个点!!! 即可返回一个字符串表示的ip地址列表,中间用英文逗号分隔。
2364 0

相关产品

  • 云解析DNS
  • 推荐镜像

    更多