zoukankan      html  css  js  c++  java
  • Node.js 实现的简易服务器 (二)

    index.js

    const server = require('./server');
    const router = require('./router');
    
    server.start(router.route);
    

    server.js

    const http = require('http');  // Node.js 内置的 http 模块
    const url = require('url');  // Node.js 内置的 url 模块
    
    
    function start(route, port=8080) {
        /**
         * 请求事件发生时调用的回调函数 (Node.js 是执行单线程异步非阻塞事件驱动的)
         */
        function requestListener(req, resp) {
            let pathname = url.parse(req.url).pathname;
            console.log(`Request for ${pathname} received.`);
    
            route(pathname, resp);
        }
    
    
        /**
         * 创建一个基础的 HTTP 服务器
         * 
         * 请求 http 模块提供的函数 createServer 创建一个服务器对象, 并调用该对象的 listen 方法监听 8080 端口
         * 
         * See Also: 
         * createServer 函数的源码解析: https://blog.csdn.net/THEANARKH/article/details/88385964
         * Node.js 是事件驱动: https://segmentfault.com/a/1190000014926921
         */
        http.createServer(requestListener).listen(port);
    
        console.log(`Server has started on ${port}`);
    }
    
    
    module.exports = {
        start
    }
    

    router.js

    const requestHandlers = require('./requestHandlers');
    
    // 路由映射/注册
    const handler = {
        '/': requestHandlers.index,
        '/index': requestHandlers.index,
        '/start': requestHandlers.start,
        '/upload': requestHandlers.upload, 
    };
    
    // 路由处理
    function route(pathname, resp) {
        console.log(`About to route a request for ${pathname}`);
        let handle = handler[pathname];
        if (typeof handle === 'function') {
            handle(resp);
            console.log(`${handle.name} was called`);
        } else {
            console.log(`No request handle found for ${pathname}`);
            requestHandlers.NotFound(resp);
        }
    }
    
    
    module.exports = {
        route
    }
    

    requestHandlers.js

    const fs = require('fs');
    
    
    function index(resp) {
        resp.writeHead(200, { 'Content-Type': 'text/html' });
    
        fs.readFile('./index.html', function (err, data) {
            resp.write(data);
            resp.end();
        });
    }
    
    
    function start(resp) {
        const exec = require('child_process').exec;
        let result = 'empty';
        
    
        setTimeout(function() {
            exec(`echo 'hello'`, function (error, stdout, stderr) {
                result = stdout;
                console.log(result);
                resp.writeHead(200,);
                resp.write(result);
                resp.end();  // 等待事件循环调用回调函数拿到结果后才完成响应
            });
        }, 10000);
    }
    
    
    function upload(resp) {
        resp.writeHead(200, { 'Content-Type': 'text/plain' });
        resp.write('Hello Upload');
        resp.end();
    }
    
    
    function NotFound(resp) {
        resp.writeHead(200, { 'Content-Type': 'text/html' });
        resp.write(`<h1>NOT FOUND</h1>`);
        resp.end();
    }
    
    
    module.exports = {
        index, 
        start,
        upload,
        NotFound
    }
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Demo</title>
    </head>
    
    <body>
        <form action="/upload" method="post">
            <h1>Hello World</h1>
        </form>
    </body>
    
    </html>
    

    特点

    • 请求处理程序进行阻塞操作时, 会阻塞其他请求的处理
      (原因: 主(执行)线程被阻塞代码阻塞后, 其余所有请求必须等待该阻塞代码处理完毕之后才能执行)
    • 请求处理程序进行非阻塞操作时, 可以正确返回响应内容
      (原因: 请求处理程序是以阻塞方式运行的, 非阻塞代码的回调函数执行时通过 resp 对象返回正确的响应内容)

    总结

    该服务器分为三层:

    • server - 用于启动服务器, 接收请求与返回响应
    • router - 用于路由注册和路由处理
    • requestHandlers - 用于编写业务逻辑, 实现各个请求处理函数

    各层之间的通信顺序为: req -> server -> router -> requestHandlers -> router -> server -> resp, 采用将服务器响应对象传递给请求处理程序, 在请求处理程序中返回响应的方式

    姊妹篇见->Node.js 实现的简易服务器 (一) (非阻塞处理存在问题)

  • 相关阅读:
    正交矩阵(部分转载)
    向量的点乘和叉乘
    随机森林
    PCA和LDA
    SIFT和SURF特征(草稿)
    12-赵志勇机器学习-Label_Propagation
    11-赵志勇机器学习-DBSCAN聚类
    09-赵志勇机器学习-k-means
    10-赵志勇机器学习-meanshift
    09-numpy-笔记-repeat
  • 原文地址:https://www.cnblogs.com/ayuuuuuu/p/13826817.html
Copyright © 2011-2022 走看看