56 Node.js服务端开发入门

技术交流QQ群:1027579432,欢迎你的加入!

欢迎关注我的微信公众号:CurryCoder的程序人生

1.服务器端基本概念
1.1 网站的组成
  • 网站应用程序主要分为两大部分:客户端和服务器端。
  • 客户端:在浏览器中运行的部分,就是用户看到并与之进行交互的界面程序。使用HTML、CSS、JavaScript构建。
  • 服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。
    请求与响应.png
1.2 Node网站服务器
  • 能够提供网站访问服务的机器就是网站服务器,它能够接收客户端的请求,能够对请求作出对应的响应
    Node网站服务器.png
1.3 IP地址
  • 互联网中设备的唯一标识,IP代表的是互联网协议地址。
1.4 域名
  • 由于IP地址难以记忆,所以产生了域名的概念。所谓域名就是平时上网时所使用的网址。可以通过这个网站https://www.ip138.com/查看域名所对应的IP地址。例如,www.baidu.com域名所对应的IP地址为36.152.44.96。
  • 虽然在地址栏中输入的是网址,但是最终还是会将域名转换为IP才能访问到指定的网站服务器。
1.5 端口
  • 端口是计算机与外界通信交流的出口,用来区分服务器电脑中提供的不同服务(例如网站服务、数据库服务、邮件服务、文件上传与下载服务等)。
    端口.png
1.6 URL
  • 同一资源定位符(URL),是专为标识Internet网上资源位置而设的一种编制方式,我们平时所说的网页地址指的即是URL
  • URL的组成:传输协议://服务器IP或域名:端口/资源所在的位置标识。例如,https://list.jd.com/list.html?cat=9987,653,655
    • http:超文本传输协议,提供了一种发布和接收HTML页面的方法。
1.7 开发过程中客户端和服务端说明
  • 在开发阶段:客户端和服务端使用同一台电脑,即开发人员自己的电脑。
    开发过程中客户端和服务端说明.png
2.创建web服务器
2.1 创建web服务器
  • 创建web服务器,如下所示:
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
3.Http协议
3.1 Http协议的概念
  • 超文本传输协议(Http)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端/服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。
    超文本传输协议.png
3.2 报文
  • 在Http请求和响应的过程中,传递的数据块就叫报文。主要包括要传送的数据和一些附加信息,并且要遵守规定好的格式。
    报文.png
3.3 请求报文
  • (1).请求方式
    • GET:请求数据
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        // 获取请求方式
        console.log(req.method);
        res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
    • POST: 发送数据
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <!-- method: 指定当前表单提交的方式 -->
        <!-- action: 指定当前表单提交的地址 -->
        <form method="POST" action="http://localhost:3000">
            <input type="submit" name="" id="">
        </form>
    </body>
    </html>
    
  • (2).请求地址RequestURL:req.headers(获取请求报文)、req.url(获取请求地址)、req.method(获取请求方法)
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        // 获取请求地址 req.url
        // console.log(req.url);
        if (req.url == '/index' || req.url == '/') {
            res.end('welcome to homepage');
        } else if (req.url == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('Not Found');
        }
    
        // 获取请求报文信息 req.headers
        console.log(req.headers['accept']);
        
    
    
    
        // 获取请求方式 req.method
        // console.log(req.method);
    
        if (req.method == 'POST') {
            res.end('post');
        } else if (req.method == 'GET') {
            res.end('get');
        }
        // res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
3.4 响应报文
  • (1).Http响应状态码
    • 200:请求成功
    • 404:请求的资源没有被找到
    • 500: 服务器端错误
    • 400: 客户端请求有语法错误
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    
    
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
    
        res.writeHead(500);
    
        // 获取请求地址 req.url
        // console.log(req.url);
        if (req.url == '/index' || req.url == '/') {
            res.end('welcome to homepage');
        } else if (req.url == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('Not Found');
        }
    
        // 获取请求报文信息 req.headers
        console.log(req.headers['accept']);
        
    
    
    
        // 获取请求方式 req.method
        // console.log(req.method);
    
        if (req.method == 'POST') {
            res.end('post');
        } else if (req.method == 'GET') {
            res.end('get');
        }
        // res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
  • (2).内容类型content-type
    • text/plain(默认)
    • text/html
    • text/css
    • application/javascript
    • image/jpeg
    • application/json
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
    
        res.writeHead(200, {
            'content-type': 'text/html;charset=utf8'
        });
    
        // 获取请求地址 req.url
        // console.log(req.url);
        if (req.url == '/index' || req.url == '/') {
            res.end('<h2>欢迎来到首页</h2>');
        } else if (req.url == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('Not Found');
        }
    
        // 获取请求报文信息 req.headers
        console.log(req.headers['accept']);
        
    
        // 获取请求方式 req.method
        // console.log(req.method);
    
        if (req.method == 'POST') {
            res.end('post');
        } else if (req.method == 'GET') {
            res.end('get');
        }
        // res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
4.Http请求与响应处理
4.1 请求参数
  • 客户端向服务端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作。
    请求参数.png
4.2 GET请求参数
  • 参数被放置在浏览器地址栏中,如:http://localhost:3000/?name=CurryCoder&age=18
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // 内置url模块:用于处理url地址
    const url = require('url');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        // 响应请求
        res.writeHead(200, {
            'content-type': 'text/html;charset=utf8'
        });
    
        // 获取请求地址 req.url
        console.log(req.url);  // /index?name=CurryCoder&age=18
        // req.url要解析的url地址,返回的是一个字符串形式的查询参数query; 再利用true将查询参数query解析成对象形式
        let {query, pathname} = url.parse(req.url, true);  // 对象结构
        console.log(query.name); 
        console.log(query.age); 
    
        if (pathname == '/index' || pathname == '/') {
            res.end('<h2>欢迎来到首页</h2>');
        } else if (pathname == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('Not Found');
        }
    
        // 获取请求报文信息 req.headers
        // console.log(req.headers['accept']);
        
    
        // 获取请求方式 req.method
        // console.log(req.method);
    
        if (req.method == 'POST') {
            res.end('post');
        } else if (req.method == 'GET') {
            res.end('get');
        }
        // res.end('<h2>hello user</h2>');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
4.3 POST请求参数
  • 参数被放置在请求体(请求报文)中进行传输。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <!-- method: 指定当前表单提交的方式 -->
        <!-- action: 指定当前表单提交的地址 -->
        <form method="POST" action="http://localhost:3000">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit" name="" id="">
        </form>
    </body>
    </html>
    
  • 获取POST参数需要使用data事件和end事件。
  • 使用querystring系统模块将参数转换为对象形式。
    // 用于创建网站服务器的模块
    const http = require('http');
    
    // 处理请求参数模块:将字符串转换成对象形式
    const querystring = require('querystring');
    
    // app对象就是网站服务器对象
    const app = http.createServer();
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        // post参数是通过事件的方式(data和end)接收的,post参数不是一次性接收完成的。所以,需要声明变量postParams,再通过变量拼接参数即可接收所有参数。
        // data:当请求参数传递时,触发data事件
        // end:当参数传递完成时,触发end事件
        let postParams = '';
        req.on('data', params => {
            postParams += params;
        });
    
        req.on('end', () => {
            console.log(querystring.parse(postParams));
        });
        res.end('OK');
    });
    
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功!');
    
4.4 路由
  • 路由是指客户端请求地址与服务端程序代码的对应关系。简单的说,就是请求什么就响应什么。如:http://localhost:3000/index或http://localhost:3000/login
    // 1.引入系统模块http
    // 2.创建网站服务器
    // 3.为网站服务器对象添加请求事件
    // 4.实现路由功能
        // (1).获取客户端的请求方式
        // (2).获取客户端的请求地址
    const http = require('http');
    const app = http.createServer();
    const url = require('url');
    
    
    app.on('request', (req, res) => {
        // 获取请求方式
        const method = req.method.toLowerCase();
        // 获取请求地址
        const pathname = url.parse(req.url).pathname;
        res.writeHead(200, {
            'content-type': 'text/html;charset=utf8'
        })
    
        if (method == 'get') {
            if (pathname == '/' || pathname == '/index') {
                res.end('欢迎来到首页');
            } else if (pathname == '/list') {
                res.end('欢迎来到列表页');
            } else {
                res.end('您访问的页面不存在');
            }
        } else if (method == 'post') {
            
        }
    });
    
    app.listen(3000);
    console.log('服务器启动成功');
    

路由.png

4.5 静态资源
  • 服务器端不需要处理,可以直接响应给客户端的资源就是静态资源。HTML、CSS、JavaScript、image文件就是静态资源。例如,不论谁访问https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png,均得到的都是下图。
    静态资源.png
  • 静态资源访问
    // 静态资源的访问
    const http = require("http");
    const app = http.createServer();
    const url = require('url');
    const path = require('path');
    const fs = require('fs');
    const mime = require('mime');
    
    app.on("request", (req, res) => {
        // 获取用户的请求路径
        let pathname = url.parse(req.url).pathname;
        pathname = pathname == '/' ? '/index.html' : pathname;
        // 将用户的请求路径转换为实际的服务器硬盘路径
        let realPath = path.join(__dirname, 'public' + pathname);
        let type = mime.getType(realPath);
        // 读取文件
        fs.readFile(realPath, 'utf8', (err, result) => {
            // 如果文件读取失败
            if (err != null) {
                res.writeHead(404, {
                    'content-type': 'text/html;charset=utf8'
                })
                res.end('文件读取失败');
                return;
            }
            res.writeHead(200, {
                'content-type': type
            })
            res.end(result);
        });
    });
    
    app.listen(3000);
    console.log("服务器启动成功");
    
4.6 动态资源
  • 相同的请求地址,不同的响应资源。这种资源就是动态资源。例如:https://blog.csdn.net/cdlwhm1217096231/article/details/106380489和https://blog.csdn.net/cdlwhm1217096231/article/details/106684950就是两篇不同的博客地址
5.Node.js异步编程
5.1 同步API、异步API
  • 同步API:只有当前API执行完成后,才能继续执行下一个API。
    console.log('before);
    console.log('after');
    
  • 异步API:当前API的执行不会阻塞后续代码的执行。
    console.log('before);
    <!-- 异步API -->
    setTimeout(() => {
        console.log('last');
    }, 2000);
    console.log('after');
    
    //  结果
    before
    after
    last
    
5.2 同步API与异步API的区别(获取返回值)
  • 区别:同步API可以从返回值中拿到API的执行结果,但是异步API是不可以的。
    // 同步API与异步API对比
    
    // 同步API
    function sum(n1, n2) {
        return n1 + n2;
    }
    
    const result = sum(10, 100);
    console.log(result);  // 110
    
    
    // 异步API
    function getMsg() {
        setTimeout(function () {
            return {
                msg: 'Hello, Node.js'
            }
        }, 2000);
    }
    const msg = getMsg();
    console.log(msg);  // undefined
    
5.3 通过回调函数返回异步API的结果
  • 回调函数:自己定义函数,让别人去调用。
    function getData(callback) {
    callback('123');
    }
    
    getData(n => {
        console.log('callback函数被调用了');
        console.log(n);
    });
    
5.4 同步API与异步API的区别(代码的执行顺序)
  • 同步API从上到下依次执行,前面的代码会阻塞后面代码的执行。
  • 异步API不会等待API执行完成后,再向下执行代码。
    // 同步API
    for (var i = 0; i < 100; i++){
        console.log(i);
    }
    
    console.log('for循环后面的代码');
    
    // 异步API
    console.log('代码开始执行');
    setTimeout(() => {
        console.log('2s后执行的代码');
        
    }, 2000);
    
    setTimeout(() => {
        console.log('0s后执行的代码');
    }, 0);
    
    console.log('代码结束执行');
    

同步API与异步API的区别(代码的执行顺序).png

6.资料下载
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值