• Node_进阶_8


    Node进阶第八天

    一、复习

    Node.js特点:单线程、异步I/O(非阻塞I/O)、事件驱动(事件环)。

    适合的程序:就是没有太多的计算,I/O比较多的业务。

    举例:留言本、考试系统、说说、图片裁切服务器。

    fs.readFile();

    gm;

    Node.js原生:http、fs、path、url、静态服务、简单路由、GET、POST请求

    模块:formidable、gm、express

    Express:Koa(koa表现力没有express丰富,但是自动集成了post处理这些东东)

    Express:中间件、MVC建站、模板引擎ejs、静态服务、简单路由、GET、POST请求。

    服务器的一些概念:Cookie、Session

                第一次之后,服务器会有一个set-cookie…然后每次就都带着

    持久化NoSQL:非关系型数据库,Not Only SQL 特点:没有schema、没有行和列。用文档(JSON)来存储。

    MongoDB:安装、开启、导入数据、Shell管理数据库,Mongo可视化工具

    Node.js做CRUD(增删改查),DAO层的封装(sqlhelper.js)

    Mongoose:ODM(是文档对象映射,对应ORM Object Relational Mapping关系对象映射) 不用直接操作数据库,操作对象,这个对象自动持久。

    Defining your Schema 定义文档结构

    Creating a model 创建一个model

    mongoose.model(modelname,schema)

    转换为对象

    定义对象的方法

    Hello World:

    //引包

    var mongoose = require('mongoose');

    //创建一个数据库连接

    mongoose.connect('mongodb://localhost/test');

     

    //创建一个Cat模型,语法mongoose.model(模型名字,Schema);

    //这里省略了一步,就是schema是通过new mongoose.schema({});

    var Cat = mongoose.model('Cat',{name:String,age:Number});

     

    //实例化,实例化的时候,new Cat(数值)

    var kitty = new Cat({name:"汤姆",age:15});

     

    //保存

    // kitty.save(function(err){

    //     console.log('meow');

    // })

     

    //寻找Tom猫,将它改为8岁

    Cat.find({'name':'汤姆'},function(err,result){

     

        var xiaomao = result[0]; //小猫这个变量是一个Cat的实例,为什么?

                                 //因为它是从Cat集合中find出来的,所以find出来之后

                                 //就是Cat的一个实例。

        xiaomao.age = 8;

        xiaomao.save();

     

        

        //new出来的是它的实例

        //找出来的也是它的实例

        //并不是使用db.update(..)..这种

        //db.update({"name":"汤姆"},{$set:{"age":8}},function(){..})

        //通过find得到了这个小猫的对象,

     

       

    });

     

    还可以嵌套

    用mongoose做学生选课系统(略过)

    二、WebSocket和Socket.IO框架

    HTTP:

    ·HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与科幻段之间不具备持续连接。

    ·我们可以非常轻松的捕获浏览器上发生的事件(比如用户点击了盒子),这个事件可以轻松产生于服务器的数据交互(比如Ajax)。但是,反过来却是不可能的:服务器端发生了一个事件,服务器无法将这个事件的信息实时主动通知它的客户端。只有在客户端查询服务器的当前状态的时候,所发生事件的信息才会从服务器传递到客户端。

    但是,确实聊天室确实存在。

    方法:

    ·长轮询:客户端每隔很短的事件,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的音响,这种做法是无脑之举,实际上对服务器,客户端双发都造成了大量的性能浪费。

    ·长连接:客户端只请求一次,但是服务器会将连接保持,不会返回结果(想象一下我们没有写res.end()时,浏览器一直转小菊花)。服务器有了新数据,就将数据发回来,又有了新数据,就将数据发回来,而一直保持挂起状态。这种做法的也造成了大量的性能浪费。

    HTML5解决了这个问题。

    WebSocket协议能够让浏览器和服务器全双工通信,互相的,服务器也能主动通知客户端了。

    ·WebSocket的原理非常的简单:利用HTTP请求产生握手,HTTP头部中WebSocket协议的请求,所以握手之后,二者转用TCP协议进行交流(QQ的协议)。 就是QQ和QQ服务器的关系了。

    所以WebSocket协议,需要浏览器支持,更需要服务器支持。

    ·使用WebSocket协议,需要浏览器和服务器都支持才可以使用。

    ·支持WebSocket协议的服务器有:Chrome 4、火狐 4、IE10、Safari5。

    ·支持WebSocket协议的服务器有:Node0、Apache7.0.2、Nginx1.3。

    Node.js上需要写一些程序,来处理TCP请求。

    Socket.IO

    ·Node.js从诞生之日起,就支持WebSocket协议,不过从底层一步一步搭建一个Socket服务器很费劲(想象一下Node写一个静态服务其都那么费劲),所以,有大神帮我们写了一个库Socket.IO。

    ·Socket.IO是业界良心,新手福音。它屏蔽了所有底层细节,让顶层调用非常简单。并且还为不支持WebSocket协议的浏览器,提供了长轮询的透明模拟机制。

    ·Node的单线程、非阻塞I/O、事件驱动机制,使它非常适合Socket服务器。

    先要npm下载这个库

    npm install socket.io

    写原生的JS,搭建一个服务器,server创建好,创建一个io对象

    var http = require('http');

     

    const server = http.createServer((req,res)=>{

        res.writeHead(200,{'Content-type':'text/html;charset=UTF-8'});

        res.end('你好');

    });

     

    var io = require('socket.io')(server);

    // 相当于:

    // var socketIo = require('socket.io');

    // var io = SocketIo(server);

     

    //监听连接事件

    io.on('connection',function(){

       console.log('1个客户端连接了');

    })

     

    server.listen(3000,()=>{console.log('running at port 3000')});

    写完这句话之后,你就会发现,http://127.0.0.1/3000/socket.io/socket.io.js就是一个js文件的地址了。

    现在需要制作一个index页面,这个页面中,必须引用秘密js文件。调用io函数,取得socket对象。

    <!DOCTYPE html>

    <html lang="en">

     

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>Document</title>

    </head>

     

    <body>

        <h1>我是index页面,我引用了秘密script文件</h1>

    </body>

     

    <script src="/socket.io/socket.io.js"></script>

    <script>

     

        var socket = io();

     

    </script>

     

    </html>

    此时,在服务器上,app.js中就要书写静态文件呈递程序,能够呈递静态页面。

    const server = http.createServer((req, res) => {

        if (req.url == '/') {   

            //显示首页

            fs.readFile('./index.html', function (err,data) {

                res.end(data);

            });

        }

    });

     

    至此,服务器和客户端都有socket对象了。

    服务器的socket对象:

    io.on

    客户端的socket对象:

    怎么回答呢:

    服务器端:

    客户端:

    io.on('connection', function (socket) {

        console.log('1个客户端连接了');

     

        socket.on('tiwen', function (msg) {

            console.log('本服务器得到了一个提问' + msg);

            // socket.broadcast.emit('huida','吃了');

            socket.emit('huida', '吃了');

        });

    })

    每一个连接上来的用户,都有一个socket,由于我们的emit语句,是socket.emit()发出,所以指的是向这个客户端发出语句。

    广播,就是给当前所有用户发送信息:

    io.on('connection', function (socket) {

        console.log('1个客户端连接了');

     

        socket.on('tiwen', function (msg) {

            console.log('本服务器得到了一个提问' + msg);

            // socket.broadcast.emit('huida','吃了');

            io.emit('huida', '吃了');

        });

    })

    改成io.emit就是群发了,轰炸。

    01.js:

    var http = require('http');

    var fs = require('fs');

     

    const server = http.createServer((req, res) => {

        if (req.url == '/') {

            //显示首页

            fs.readFile('./index.html', function (err, data) {

                res.end(data);

            });

        }

    });

     

    var io = require('socket.io')(server);

    // 相当于:

    // var socketIo = require('socket.io');

    // var io = SocketIo(server);

     

    //监听连接事件

    io.on('connection', function (socket) {

        console.log('1个客户端连接了');

     

        socket.on('tiwen', function (msg) {

            console.log('本服务器得到了一个提问' + msg);

            // socket.broadcast.emit('huida','吃了');

            io.emit('huida', msg);

        });

    });

     

    server.listen(3000, () => { console.log('running at port 3000') });

    index.html:

    <!DOCTYPE html>

    <html lang="en">

     

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>Document</title>

    </head>

     

    <body>

        <h1>我是index页面,我引用了秘密script文件</h1>

        <input type="text" value="" id="wenben" width="500" />

        <input type="button" value="发送消息给全班" id="btn" />

    </body>

     

    <script src="/socket.io/socket.io.js"></script>

    <script>

     

        var socket = io();

     

        //点击按钮之后,发出提问

        document.getElementById('btn').onclick = function () {

            socket.emit('tiwen', document.getElementById('wenben').value);

        }

     

        socket.on('huida', function (msg) {

            console.log('服务器说它' + msg);

        });

     

    </script>

     

    </html>

    小小聊天室

     

    chat.ejs:

    <!DOCTYPE html>

    <html lang="en">

     

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>Document</title>

        <style>

            .caozuo {

                position: fixed;

                bottom: 0;

                left: 0;

                height: 100px;

                background-color: #ccc;

                100%;

            }

     

            .caozuo input {

                font-size: 30px;

            }

     

            .caozuo input[type=text] {

                100%;

            }

        </style>

    </head>

     

    <body>

     

        <h1>小小聊天室

            <span id="yonghu">

                <%=yonghuming%>

            </span>

        </h1>

        <div>

            <ul class="liebiao">

            </ul>

        </div>

     

        <div class="caozuo">

            <input type="text" id="neirong">

        </div>

     

    </body>

    <script src="/socket.io/socket.io.js"></script>

    <script src="/js/jquery.min.js"></script>

    <script>

        var socket = io();

        $('#neirong').keydown(function (e) {

     

            if (e.keyCode == 13) {

     

                //把文本框的内容上传

                socket.emit('liaotian', {

                    neirong: $('#neirong').val(),

                    ren: $("#yonghu").html()

                });

     

                $(this).val("");

     

            }

     

        });

     

        $('#fayan').click(function () {

            //把文本框的内容上传

            socket.emit('liaotian', {

                neirong: $('#neirong').val(),

                ren: $("#yonghu").html()

            });

        });

     

        socket.on('liaotian', function (msg) {

            $('.liebiao').append("<li><b>" + msg.ren + ": </b>" + msg.neirong + "</li>");

        });

     

    </script>

     

    </html>

    index.ejs:

    <!DOCTYPE html>

    <html lang="en">

     

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>Document</title>

        <style>

            div {

                700px;

                height: 30px;

                padding: 40px;

                border: 1px solid #000;

                margin: 0 auto;

            }

        </style>

    </head>

     

    <body>

        <div>

            <form action="/check" method="get">

                输入昵称:

                <input type="text" id="yonghuming" name="yonghuming" />

                <input type="submit" value="进入聊天室">

            </form>

        </div>

    </body>

     

    </html>

    app.js:

    var express = require('express');

    var app = express();

    //socket.io公式

    var http = require('http').Server(app);

    var io = require('socket.io')(http);

    //session公式

    var session = require('express-session');

     

    app.use(session({

        secret: 'keyboard cat',

        resave: false,

        saveUninitialized: true

    }));

     

    //模板引擎

    app.set('view engine', 'ejs');

    //静态服务

    app.use(express.static('./public'));

     

    var alluser = [];

     

    //中间件

    //显示首页

    app.get('/', function (req, res, next) {

        res.render('index');

    });

     

    //确认登陆 检查此人是否有用户名,并且昵称不能重复

    app.get('/check', function (req, res, next) {

     

        var yonghuming = req.query.yonghuming;

        if (!yonghuming) {

            res.send('必须填写用户名');

            return;

        }

        if (alluser.indexOf(yonghuming) != -1) {

            res.send('用户名已经被占用');

            return;

        }

        alluser.push(yonghuming);

        //付给session

        req.session.yonghuming = yonghuming;

      

     

        res.redirect('/chat');

    });

     

    //聊天室

    app.get('/chat', function (req, res, next) {

     

        //这个页面必须保证有用户名了,

        if(!req.session.yonghuming){

            res.redirect('/');

            return;

        }

        res.render('chat',{

            yonghuming:req.session.yonghuming

        });

    })



    io.on('connection', function (socket) {

        socket.on('liaotian', function (msg) {

           //把接收到的msg原样广播

            io.emit('liaotian', msg);

        });

    });

     

    //监听

    http.listen(2998);

    小小画板

     

     

    Socket完成点对点

    靠服务器转发,把两个人放在一个聊天室内其实就是点对点了。

  • 相关阅读:
    不吐不快之EJB演练——开篇概述
    URL重写:RewriteCond指令与RewriteRule 指令格式
    刚到公司有点压力山大,在此希望有大神给点正能量
    053第449题
    选择排序---简单选择排序 堆排序
    bzoj-1492 货币兑换Cash (2)——CDQ分治
    MySQL 提高Insert性能
    Codeforces Round #313 (Div. 2) 560C Gerald&#39;s Hexagon(脑洞)
    Matlab矩阵基础
    Android 带清除功能的输入框控件EditTextWithDel
  • 原文地址:https://www.cnblogs.com/eret9616/p/9111521.html
Copyright © 2020-2023  润新知