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;

            width: 100%;

        }

 

        .caozuo input {

            font-size: 30px;

        }

 

        .caozuo input[type=text] {

            width: 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 {

            width: 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完成点对点

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

猜你喜欢

转载自www.cnblogs.com/eret9616/p/9111521.html