美文网首页我爱编程
Node.js 教程|实验代码+运行结果

Node.js 教程|实验代码+运行结果

作者: 茱小夭 | 来源:发表于2017-08-27 17:01 被阅读0次

    课程来源:https://www.shiyanlou.com/courses/44【@实验楼】

    第一节 Node.js课程介绍

    1 查看系统中安装的Node.js版本 2 测试Node.js的控制台输出 3.1 在桌面新建test.js文件 3.2 通过Node.js 交互环境运行文件

    笔记

    一个js文件就是一个模块,而包是一个文件夹,包内必须包含一个JSON文件,命名为package.json。

    • bin文件夹:二进制文件
    • lib文件夹:js文件
    • doc文件夹:文档
    • test文件夹:单元测试
    • package.json

    第二节 Node.js模块

    一、暴露一个文件里的多个函数

    exports.引用名(自定义) = 函数名;
    exports.引用名(自定义) = 函数名;
    ……

    mymodule.js index.js 结果

    二、暴露一个文件里的一个函数

    module.exports = 函数名;

    mymodule.js index.js 结果

    笔记

    npm init //创建package.json文件

    package.json

    npm search express //搜索express包
    npm install -g express //安装包,-g即global全局安装
    npm updata express //更新包
    npm uninstall express //卸载包


    第三节 Node.js Events模块

    一、添加监听器

    emitter.addListener(event,listener)
    emitter.on(event,listener)

    1.1 新建test.js 1.2 运行代码 1.3 在浏览器输入'127.0.0.1337'每刷新一次会出现一个'shiyanlou'

    二、只执行一次的监听器

    emitter.once(event,listener)

    2.1 新建test2.js 2.1 刷新浏览器,不再出现'shiyanlou'

    三、移除监听器

    emmiter.removeListener(event,listener)

    3.1 新建test3.js 3.2 运行代码 3.3 出现了'shiyanlou',没有出现'Hello World'

    四、移除所有监听器

    emmiter.removeAllListeners([event])

    4.1 新建test4.js 4.2 运行代码 4.3 只出现了'shiyanlou'

    五、设置监听器最大绑定数

    emitter.setMaxListners(n)

    • 默认情况,超过10个就会警告提示
    • n = 0,无限制

    六、自定义事件

    emitter.emit(event,[arg1],[arg2],[...])

    6.1 新建test5.js 6.2 运行及结果

    七、查看事件绑定的监听器个数

    EventEmitter.listenerCount(emitter,event)

    7.1 新建test6.js 7.2 运行及结果

    第四节 Node.js fs模块

    一、异步和同步

    fs.unlink(filename,callback); //异步

    异步实例

    fs.unlinkSync(filename); //同步

    同步实例

    二、readFile读取文件

    fs.readFile(filename,[options],callback)

    fs.readFile参数

    原始二进制数据在缓冲区的内容

    2.1 新建text.txt 2.2 新建readfile.js 2.3 运行及结果

    使用toString()或者设置输出编码,修改readFile.js

    text.js 运行及结果

    三、writeFile写入文件

    fs.writeFile(filename,data,[options],callback)

    fs.write参数 3.1 新建writeFile.js 3.1.1 运行及结果 3.1.2 运行及结果

    如果要追加数据到文件,可以传递一个flag参数

    • r :read
    • w :write
    • a :append
    • ……
    flag:a 运行及结果

    四、使用fs.read和fs.write读写文件

    fs.open(path,flags,[mode],callback) 打开文件

    • mode:文件的权限,默认值0666
    • flags的值

    fs.close(fd,[callback]) 关闭文件

    • fd:所打开文件的文件描述符

    4.1 fs.read()

    fs.read(fd,buffer,offset,length,position,callback)

    • fs.read参数
    4.1.1 新建testread.txt 4.1.2 新建read.js 4.1.3 运行及结果

    4.2 fs.write()

    fs.write(fd,buffer,offset,length,position,callback)

    4.2.1 新建write.js 4.2.2.1 运行及结果 4.2.2.2 运行及结果

    遇到的问题

    在实验4.2中


    修改后的代码

    文档中的实验代码是fs.write(fd,buffer,0,6,0……),实际上应该只写入了‘shiyan’


    本意应该是输出写入的内容
    但是,如上所述的read代码,无论写入多少位内容,都会输出‘shiyanlou’,所以为了保持一致,我将源码进行了修改。

    五、目录操作

    5.1 创建目录

    fs.mkdir(path,[mode],callback)

    • path:需要创建的目录
    • mode:目录的权限

    fs.rmdir(path,mkdir)

    • 只能删除空目录
    5.1.1 新建mkdir.js 5.1.2 运行及结果

    5.2 读取目录

    fs.readdir(path,callback)

    5.2.1 新建readdir.js 5.2.2 在newdir文件夹中新建'dir1文件夹'和'file1文件' 5.2.3 运行及结果

    第五节 Node.js的http模块

    一、创建 http server

    1.1 通过Node.js创建(简单方式)

    1.1.1 新建 demo.js 1.1.2 运行及结果

    1.2 复杂方式

    新建app文件夹,在app文件夹中新建server.js,代码如下:

    /*
    创建 http server
     */
    
    
    // 加载所需模块
    var http = require('http');
    var url = require('url');
    var fs = require('fs');
    
    // 设置ip和端口
    // 实际应用中,可以把这些写到配置文件中
    var host = '127.0.0.1',
        port = 8080;
    
    // 创建http server
    function start(route, handle) {
        // 参数
        // route  判断url是否存在,存在则调用handle处理,不存在则返回404
        // handle 处理不同的url请求
    
    
        // 处理request请求
        function onRequest(req, res) {
            // 使用url.parse()方法解析url
            // 它会把url string转化为一个object
            // 这样我们就可以很方便的获取url中的host、port、pathname等值了
            var pathname = url.parse(req.url).pathname;
            console.log('Request for ' + pathname + ' received.');
    
            // 判断并处理不同url请求
            // 后面介绍此方法
            route(handle, pathname, res, req);
        }
    
        // 使用http.createSserver()方法创建http server
        // 并传入onRequest()方法
        // 然后使用listen()方法监听指定地址
        http.createServer(onRequest).listen(port, host);
        console.log('Server has started and listening on ' + host + ':' + port);
    }
    
    // 导出 start 方法
    exports.start = start;
    

    二、创建路由

    2.1 在app文件夹中新建router.js,代码如下:

    var fs = require('fs');
    
    // 路由函数
    // 处理不同url的请求
    // 并返回相应内容
    
    function route(handle, pathname, res, req) {
        console.log('About to route a request for ' + pathname);
    
        // 判断url是否存在特定处理函数
        // 存在则调用handle处理
        // 不存在则返回404页面
        if (typeof handle[pathname] === 'function') {
            // handle用于处理不同的url请求
            handle[pathname](res, req);
        } else {
            console.log('No request handler found for ' + pathname);
    
            // 读取404页面
            // 所有页面都存放在view文件夹下
            var content = fs.readFileSync('./views/404.html');
            res.writeHead(404, {'Content-Type': 'text/html'});
            res.write(content);
            res.end();
        }
    }
    
    // 导出route方法
    exports.route = route;
    

    2.2 在app文件夹中新建requestHandlers.js文件,代码如下:

    // 处理url请求
    // 读取文件,输出到response
    
    var fs = require('fs');
    
    // home.html主页
    function home(res) {
        console.log('Request handler "home" was called.');
    
        // 读取home.html文件
        var content = fs.readFileSync('./views/home.html');
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(content);
        res.end();
    }
    
    // about.html关于页面
    function about(res) {
        console.log('Request handler "about" was called.');
    
        // 读取about.html文件
        var content = fs.readFileSync('./views/about.html');
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(content);
        res.end();
    }
    
    // 导出页面处理函数
    exports.home = home;
    exports.about = about;
    

    三、创建主程序

    3.1 在app文件夹新建main.js文件,代码如下:

    // 主程序
    
    // 引入server,router及requestHandler
    var server = require('./server');
    var router = require('./router');
    var requestHandlers = require('./requestHandlers');
    
    // 保存url处理方法
    var handle = {};
    handle['/'] = requestHandlers.home;
    handle['/about'] = requestHandlers.about;
    
    // 启动http server
    server.start(router.route, handle);
    

    四、创建HTML文件

    在app文件夹中新建views文件夹,在views文件夹中,新建home.html文件、about.html文件和404.html文件。

    4.1 home.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Home page</title>
        </head>
        <body>
            <p>home page</p>
        </body>
    </html>
    

    4.2 about.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>About page</title>
        </head>
        <body>
            <p>about page</p>
        </body>
    </html>
    

    4.3 404.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>404 page</title>
        </head>
        <body>
            <p>404 page not found</p>
        </body>
    </html>
    

    五、运行及结果

    5.1 运行main.js 5.2.1 地址栏输入127.0.0.1:8080 5.2.2 地址栏输入127.0.0.1:8080/about 5.2.3 地址栏输入127.0.0.1:8080/others

    第六节 Node.js中的网络编程

    一、TCP Server

    net模块通过net.createServer方法创建TCP服务器,通过net.connect方法创建客户端去连接服务器。

    1.1 新建server.js

    var net = require('net');
    
    // 创建TCP服务器
    var server = net.createServer(function (socket) {
        console.log('client connected');
    
        // 监听客户端的数据
        socket.on('data', function (data) {
            console.log('server got datta from client:', data.toString());
        });
        // 监听客户端断开连接事件
        socket.on('end', function (data) {
            console.log('connection closed');
        });
        // 发送数据给客户端
        socket.write('Hello\r\n');
    });
    
    // 启动服务
    server.listen(8080, function () {
        console.log('server bound');
    });
    

    1.2 新建 client.js

    var net = require('net');
    
    // 连接服务器
    var client = net.connect({port: 8080}, function () {
        console.log('connected to server');
        client.write('World!\r\n');
    });
    
    // 接收服务端的数据
    client.on('data', function (data) {
        console.log('client got data from server:', data.toString());
        // 断开连接
        client.end();
    });
    
    // 断开连接
    client.on('end', function () {
        console.log('disconneected from server');
    });
    

    1.3 运行及结果

    • 先在一个终端 运行server.js
    • 再在另一个终端 运行client.js
    1.3.1 server.js结果 1.3.2 client.js结果

    二、简易聊天室

    2.1 服务端——新建chatServer.js,代码如下:

    var net = require('net');
    
    // 创建TCP服务器
    var server = net.createServer();
    // 存储所有客户端socket
    var sockets = [];
    
    // 接受客户端连接请求
    server.on('connection', function (socket) {
        console.log('Got a new connection');
    
        // 接收所有的用户连接(因为是聊天室,允许多个客户端用户同时连接)
        sockets.push(socket);
    
        // 获取客户端发送过来的数据
        socket.on('data', function (data) {
            console.log('Got data:', data.toString());
    
            // 服务器广播数据,把来自客户端的数据转发送给其他所有客户端
            sockets.forEach(function (otherSocket) {
                if (otherSocket !== socket) {
                    otherSocket.write(data);
                }
            });
        });
    
        // 把需要关闭连接的客户端从服务器广播列表中给删除掉
        socket.on('close', function () {
            console.log('A client connection closed');
            var index = sockets.indexOf(socket);
            sockets.splice(index, 1);
        });
    });
    
    server.on('error', function (err) {
        console.log('Server error:', err.message);
    });
    
    server.on('close', function () {
        console.log('Server closed');
    });
    
    server.listen(8080);
    

    2.2 客户端,新建chatClient.js,代码如下:

    var net = require('net');
    
    process.stdin.resume();
    process.stdin.setEncoding('utf8');
    
    var client = net.connect({port: 8080}, function () {
        console.log('Connected to server');
    
        // 获取输入的字符串
        console.log('input:');
        process.stdin.on('data', function (data) {
            // 发送输入的字符串到服务器
            console.log('input:');
            client.write(data);
    
            // 输入'close'字符串时关闭连接
            if (data == 'close\n\n') {
                client.end();
            }
        });
    });
    
    // 获取服务器端发送过来的数据
    client.on('data', function (data) {
        console.log('Other user\'s input', data.toString());
    });
    
    client.on('end', function () {
        console.log('Disconnected from server');
        // 退出客户端程序
        process.exit();
    });
    

    2.3 运行及结果

    • 先在一个终端 运行chatServer.js
    • 再在另一个终端 运行chatClient.js
    • 再在再在另一个终端 运行chatClient.js
    服务器端 客户端-1 客户端-2

    遇到的问题

    从运行结果截图可以看出,能正常聊天,但是输入‘close’时却无法正常退出!

    三、UDP Server

    3.1 服务端——新建udpServer.js,代码如下:

    var dgram = require('dgram');
    
    var server = dgram.createSocket('udp4');
    
    server.on('error', function (err) {
        console.log('serevr error:\n' + err.stack);
        server.close();
    });
    
    // 接收来自客户端的消息
    server.on('message', function (msg, rinfo) {
        console.log('server got:' + msg.toString() + 'from' + rinfo.port);
    });
    
    // 监听服务
    server.on('listening',function(){
        var address = server.address();
        console.log('server listening on '+address.address+':'+address.port);
    });
    
    server.bind(41234);
    // server listening 0.0.0..0:41224
    

    3.2 客户端——新建udpClient.js,代码如下:

    var dgram = require('dgram');
    
    var client = dgram.createSocket('udp4');
    
    // 发送的消息必须通过Buffer创建
    var message = new Buffer('hello shiyanlou!\n');
    
    client.send(message, 0, message.length, 41234, 'localhost', function (err, bytes) {
        client.close();
    });
    

    3.3 运行及结果

    • 先在一个终端 运行updServer.js
    • 再在另一个终端 运行udpClient.js
    服务端 客户端

    笔记

    • 作为web服务器软件,Node.js提供了net模块用于tcp通信,dgram模块用于udp通信
    • net.createServer()用于创建tcp监听服务器,net.connect()用于客户端连接tcp服务器
    • dgram模块通过dgram.createSocket()创建udp socket,通过bind()监听特定端口,通过send()向特定socket发送信息

    第七节 Node.js中的进程

    • process模块用于提供和程序主程序有关的功能
    • child_process用于创建子程序
    • cluster用于处理集群相关编程

    一、process模块

    1.1 退出事件(exit)

    • exit事件的回调函数中接收同步操作,并且回调函数只接受一个参数
    • 在exit事件之前还有一个beforeExit事件会被触发,在beforeExit的回调函数中可以异步操作
    • 通过process.exit()退出程序或者因为发生错误而退出程序是不会触发beforeExit事件的
    • 当有错误未被捕获时,就会触发uncauhgtException事件

    新建try-exit.js,代码如下:

    process.on('exit', function (code) {
        setTimeout(function () {
            console.log('This will not run');
        }, 0);
    
        console.log('exit code', code);
    });
    
    运行结果

    上述代码中,setTimeout方法中的回调函数不会被执行

    1.2 信号事件

    信号事件就是接受到某个特定信号才会被触发的事件。

    新建sigint.js,代码如下:

    process.stdin.resume();
    
    process.on('SIGINT', function () {
        console.log('Got SIGINT.');
    });
    
    先运行,按Ctrl-C触发‘SIGINT’事件

    1.3 属性

    IO 输入输出主要有三个

    • process.stdin // 标准输入
    • process.stdout // 标准输出
    • process.stderr // 标准错误
    遇到的问题

    新建stdin.js,源代码如下:

    process.stdin.setEncoding('utf8');
    
    process.stdin.on('readable', function() {
        var chunk = process.stdin.read();
        if (chunk !== null) {
            process.stdout.write('data: ' + chunk);
        }
    });
    
    process.stdin.on('end', function() {
        process.stdout.write('end');
    });
    
    运行结果

    当无内容输入时,可触发end事件,但结果里按回车没有触发,因为'\n'算两个字符,所以修改代码如下:

    process.stdin.setEncoding('utf8');
    
    process.stdin.on('readable', () => {
        var chunk = process.stdin.read();
    
        // 新增的代码
        if (typeof chunk === 'string') {
            chunk = chunk.slice(0, -2);
            process.stdout.write(`stringLength:${chunk.length}\n`);
        }
        if (chunk === '') {
            process.stdin.emit('end');
            return;
        }
    
        if (chunk !== null) {
            process.stdout.write(`data: ${chunk}\n`);
        }
    });
    
    process.stdin.on('end', () => {
        process.stdout.write('end');
    });
    
    运行结果

    1.4 方法

    • process.cwd() //返回脚本运行工作目录
    • process.chdir() //切换工作目录
    • process.exit() //退出当前进程
    • process.on() //添加监听事件
    • ...

    二、child_process模块

    用于创建子进程

    2.1 child_process.spawn()方法

    新建test_spawn.js,代码如下:

    var spawn = require('child_process').spawn,
        ls = spawn('ls', ['-lh', '/usr']);
    
    ls.stdout.on('data', function (data) {
        console.log('stdout: ' + data);
    });
    
    ls.stderr.on('data', function (data) {
        console.log('stderr: ' + data);
    });
    
    ls.on('close', function (code) {
        console.log('child process exited with code ' + code);
    });
    
    运行结果

    2.2 child_process.exec()方法

    在shell中运行一个命令,并缓存其输出

    新建test_exec.js 运行结果

    2.3 child_process.execFile()方法

    与exec方法类似,执行特定程序文件,参数通过一个数组传递

    新建test_execfiel.js 运行结果

    2.4 child_process.fork()方法

    • fork('./sub.js')相当于spwan('node','./sub.js')
    • fork还会在父进程和子进程之间,建立一个通信管道,通过child.send()发送消息
    2.4.1 新建main.js 2.4.2 新建sub.js 2.4.3 运行及结果
    遇到的问题
    在windows运行test_spawn.js 错误原因

    所以该模块实验选择了实验楼配置的Linux环境

    三、cluster模块

    单个的Node实例运行在单个线程中。要发挥多核系统的能力,需要启动一个Node进程集群来处理负载。cluster模块就用于创建共享服务器端口的子进程。

    3.1 新建 test_cluster.js 3.2 运行及结果

    相关文章

      网友评论

        本文标题:Node.js 教程|实验代码+运行结果

        本文链接:https://www.haomeiwen.com/subject/lumilxtx.html