node.js构建服务器

一.服务器与客户端

1.服务器的类型

web服务器:安装apache, tomcat, iis, nginx, 或者在nodejs环境写代码 提供:图片浏览,新闻浏览....等服务的服务器。

ftb服务器:安装serv-U软件,为其它电脑提供文件下载,共享服务

数据库服务器:安装mysql软件,为其它电脑提供数据库服务。

2.服务器相关概念

2.1http协议:

  • HTTP(HyperText Transfer Protocol) 超文本传输协议。

  • 协议双方: 浏览器与web服务器都要遵守的协议

  • 请求通常是由浏览器发起的

  • HTTP 协议中明确规定了请求数据响应数据的格式(报文)

    • 浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)

    • 服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)

2.2域名和IP:

IP(Internet Protocol Address): 用于标识一个网络设备在某个网络中的地址,计算机中的ip是唯一的,不允许相同

域名:ip地址的别名

2.3端口:

使用ip+端口的方式区分不同服务,用于提供不同的服务,一个IP端口可以有65536个,范围从[0,65535]

一些端口是已经被预定的例如http:80  https:443  mysql:3306 ,使用终端命令netstat -a -n -o可以查看端口使用情况

2.4URL(Uniform Resource Location):

统一资源定位符:作用:定位资源

格式:协议://主机地址:端口/路径?查询字符串#锚点


二.自己写一个简单的web服务器

补充:命令ipconfig可以查询到本机ip地址

         命令ping+地址可以查询丢包率等等信息

1.实现代码:

//导入核心模块
const http = require("http");
//创建http服务,参数是一个回调函数,当接收到http请求时,被调用
//回调函数有两个参数:req 客户端的请求  res 本次请求的响应
const server = http.createServer((req, res) => {
  console.log("正在被访问...");
  //设置响应头,如果不设置这个,中文会返回一串乱码
  res.setHeader("content-type", "text/html;charset=utf8");
  //向客户端发送内容,并结束本次响应
  res.end("您正在访问服务器");
});
//监听端口请求
server.listen("8081", () => {
  console.log("服务器于端口8081就绪...");
});

利用ipconfig查询本机IPv4 地址 在浏览器使用 http://IPv4 地址:设置端口码 就可以在浏览器打开,你的朋友如果和你同处一个网络中,也可以通过这个地址访问你的网页.

如果你想停止服务在终端中使用命令 ctrl + c 就可以停止了

这个作用原理就是使用http模块将本机变成一个虚拟服务器,用它来接收浏览器的请求,并响应.

如果修改了服务器的代码,需要重启才能生效

2.请求与响应

请求:当webf服务器就绪后,如果没有客户端来访问它,就不会有效果,回调函数也不会执行.每次请求,回调函数均会被调用一次

响应:res.end()可以返回一个buffer或string格式的文本


三.处理不同请求的服务器

1.实现代码:

//导入核心模块
const http = require("http");
const fs = require("fs");
const path = require("path");
//创建服务
const server = http.createServer((req, res) => {
  //可以利用req.url,判断根据不同请求,不同响应
  let { url } = req;//解构赋值
  //拼接路径
  let filepath = path.join(__dirname, "demo", url);
  //判断
  if (url === "/index.html") {
    fs.readFile(filepath, (err, data) => {
      if (err) {
        res.statusCode === 404;
        res.end("no found");
      } else {
        //根据不同的类型设置不同返回头
        res.setHeader("content-type", "text/html;charset=utf8");
        res.end(data);
      }
    });
  }
  //再判断
  else if (url === "/style.css") {
    fs.readFile(filepath, (err, data) => {
      if (err) {
        res.statusCode === 404;
        res.end("no found");
      } else {
        res.setHeader("content-type", "text/css;charset=utf8");
        res.end(data);
      }
    });
  } else if (url === "/index.js") {
    fs.readFile(filepath, (err, data) => {
      if (err) {
        res.statusCode === 404;
        res.end("no found");
      } else {
        res.setHeader("content-type", "application/javascript;charset=utf8");
        res.end(data);
      }
    });
  }
});
//监听端口
server.listen(8082);

2.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;charset=utf8')

  • .png:res.setHeader('content-type', 'image/png')

  • json数据:res.setHeader('content-type', 'application/json;charset=utf-8')


四.二次请求

有时,一个文件中引入了其他文件,例如一个html文件引入了css,js等文件,浏览器在解析过程中又发现还有外部资源,于是浏览器会再次发出请求,来获得相应资源

上一套代码发现太过于繁琐

1.改进实现代码

//导入模块
const http = require("http");
const path = require("path");
const fs = require("fs");
const { consumers } = require("stream");
//创建服务
const server = http.createServer((req, res) => {
  console.log("正在被访问中...");
  //判断
  //如果不写请求,默认是index.html
  let burl = req.url === "/" ? "index.html" : req.url;
  let url = path.join(__dirname, "demo", burl);
  fs.readFile(url, (err, data) => {
    if (err) {
      res.statusCode = 404;
      res.end("no found");
    } else {
      res.end(data);
    }
  });
});
//监听端口
server.listen(8083, () => {
  console.log("服务器已于8083端口启动...");
});

使用这套代码就简洁了很多,这种叫批量处理静态资源请求

但是上面的代码没有响应头

2.添加响应头

//在其中增加对象,利用对象进行判断

//导入模块
const http = require("http");
const path = require("path");
const fs = require("fs");
const { consumers } = require("stream");
//常见的一些conten-type 策略模式
let obj = {
  ".png": "image/png",
  ".jpg": "image/jpg",
  ".html": "text/html;charset=utf8",
  ".js": "application/javascript;charset=utf8",
  ".css": "text/css;charset=utf8",
};
//创建服务
const server = http.createServer((req, res) => {
  console.log("正在被访问中...");
  //判断
  //如果不写请求,默认是index.html
  let burl = req.url === "/" ? "index.html" : req.url;
  let url = path.join(__dirname, "demo", burl);
  //获取后缀名
  let extname = path.extname(url);
  fs.readFile(url, (err, data) => {
    if (err) {
      res.statusCode = 404;
      res.end("no found");
    } else {
      //增加判断,如果文件名存在在对象中,那就使用
      if (obj[extname]) {
        res.setHeader("content-type", obj[extname]);
      }
      res.end(data);
    }
  });
});
//监听端口
server.listen(8083, () => {
  console.log("服务器已于8083端口启动...");
});

五.静态资源与接口

1.静态资源:

不会改变的资源,一般表现为某个文件,处理请求静态资源时,服务器一般就直接读出资源的内容,再返回给客户端浏览器.

2.接口:

它们不是以某个具体的文件存在的,而是服务器上的一段代码,访问接口时,服务器会执行这段代码,然后把代码的执行结果返回给客户端浏览器。

3.写一个get请求的接口

//导入核心模块
const http = require("http");
const path = require("path");
const fs = require("fs");
//创建服务
let server = http.createServer((req, res) => {
  console.log("访问中...");
  //获取路径
  let url = path.join(__dirname, "db", "data.json");
  //判断请求接口,以及请求方式
  if (req.url === "/getList" && req.method === "GET") {
    // 读取文件
    fs.readFile(url, "utf8", (err, data) => {
      res.end(data);
    });
  } else {
    res.statusCode = 404;
    res.end("no found");
  }
});
//监听端口
server.listen("8084", () => {
  console.log("8084就绪...");
});

(未完待续...)

上一篇:文件包含漏洞


下一篇:require 与 import 的区别