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

简介: 在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?

后记

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

相关文章
|
4天前
|
消息中间件 监控 JavaScript
Node.js中的进程管理:child_process模块与进程管理
【4月更文挑战第30天】Node.js的`child_process`模块用于创建子进程,支持执行系统命令、运行脚本和进程间通信。主要方法包括:`exec`(执行命令,适合简单任务)、`execFile`(安全执行文件)、`spawn`(实时通信,处理大量数据)和`fork`(创建Node.js子进程,支持IPC)。有效的进程管理策略涉及限制并发进程、处理错误和退出事件、使用流通信、谨慎使用IPC以及监控和日志记录,以确保应用的稳定性和性能。
|
5天前
|
缓存 负载均衡 网络协议
【亮剑】一次完整的 HTTP 请求过程,包括 DNS 解析、TCP 握手、HTTP 请求和响应等环节
【4月更文挑战第30天】本文介绍了HTTP请求的重要性和详细过程。首先,DNS解析将域名转换为IP地址,通过递归和迭代查询找到目标服务器。接着,TCP三次握手建立连接。然后,客户端发送HTTP请求,服务器处理请求并返回响应。最后,理解这个过程有助于优化网站性能,如使用DNS缓存、HTTP/2、Keep-Alive、CDN和负载均衡等实践建议。
|
6天前
|
缓存 JavaScript 前端开发
Node.js的模块系统:CommonJS模块系统的使用
【4月更文挑战第29天】Node.js采用CommonJS作为模块系统,每个文件视为独立模块,通过`module.exports`导出和`require`引入实现依赖。模块有独立作用域,保证封装性,防止命名冲突。引入的模块会被缓存,提高加载效率并确保一致性。利用CommonJS,开发者能编写更模块化、可维护的代码。
|
6天前
|
XML 网络协议 应用服务中间件
Nginx应用进阶HTTP核心模块配置小结(下)
Nginx应用进阶HTTP核心模块配置小结(下)
15 1
|
6天前
|
存储 算法 应用服务中间件
Nginx应用进阶HTTP核心模块配置小结(上)
Nginx应用进阶HTTP核心模块配置小结
17 1
|
7天前
|
前端开发 API UED
AngularJS的$http服务:深入解析与进行HTTP请求的技术实践
【4月更文挑战第28天】AngularJS的$http服务是核心组件,用于发起HTTP请求与服务器通信。$http服务简化了通信过程,通过深入理解和实践,能构建高效、可靠的前端应用。
|
20天前
|
JavaScript API
node.js之模块系统
node.js之模块系统
|
22天前
|
Web App开发 JavaScript 前端开发
【Node系列】node核心模块util
Node.js的核心模块util为开发者提供了一些常用的实用工具函数。这些函数能够很方便地进行对象的继承、类型判断以及其他工具函数的实现。
22 2
|
22天前
|
域名解析 网络协议 JavaScript
【Node系列】node工具模块
Node.js有多个内置的工具模块,这些模块提供了用于执行各种任务的功能。
22 2
|
22天前
|
缓存 并行计算 JavaScript
【Node系列】模块系统
Node.js 的模块系统是其核心特性之一,允许开发者编写可复用的代码,并通过简单的导入和导出机制来共享和使用这些模块。
19 3

相关产品

  • 云解析DNS
  • 推荐镜像

    更多