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

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

Node_进阶_8的更多相关文章

  1. Node_进阶_7

    Node进阶第七天 一.复习 一.索引   数据库中,根据一个字段的值,来寻找一个文档,是很常见的操作.比如根据学号来找一个学生.这个学号是唯一的.只要有学号,就能唯一确认一个学生的文档.学号这个属性 ...

  2. Node_进阶_6

    Node进阶第六天 一.复习 cookie是在res中设置,req中读取的.第一次的访问没有cookie. cookie的存储大小有限,kv对儿.对用户可见,用户可以禁用.清除cookie.可以被篡改 ...

  3. Node_进阶_5

    Node进阶第五天 为什么mysql不用开mongod –dbpath xx… 答:因为mysql会在”服务”中运行,也就是开机时自动启动并且长久驻扎在内存中了. mongodb其实也能通过设置来设成 ...

  4. Node_进阶_4

    Node进阶第四天 一.传统数据库技术回顾 数据库就是存储数据的,那么存储数据用txt就行了啊,为什么要有数据库? 理由之一:数据库有行.列的概念,数据有关系,数据不是散的. 老牌数据库,比如Mysq ...

  5. Node_进阶_2

    第二天 一.复习: Node.js开发服务器.数据.路由.本地关心效果,交互. Node.js实际上是极客开发出的一个小玩具,不是银弹.有着别人不具备的怪异特点: 单线程.非阻塞I/O.事件驱动. 实 ...

  6. Node_进阶_1

    第一天 1.1简介 Node.js简介 V8引擎本身就是用于Chrome浏览器的JS解释部分,Ryan Dahl把这个V8搬到了服务器上,用于做服务器的软件. Node.js是一个让Javascrip ...

  7. Node_进阶_3

    Express框架: 一.   Express框架 Express框架是后台的Node框架,类似于JS中的jquery. #原生Node开发会有很多问题: 1呈递静态页面很不方便,需要处理每个HTTP ...

  8. TypeScript完全解读(26课时)_8.ES6精讲-ES6中的类(进阶)

    8.TypeScript完全解读-ES6精讲-类(进阶) 在index.ts内引入 Food创建的实例赋值给Vegetabled这个原型对象,这样使用Vegetables创建实例的时候,就能继承到Fo ...

  9. PythonI/O进阶学习笔记_8.python的可迭代对象和迭代器、迭代设计模式

     content: 1.什么是迭代协议 2. 什么是迭代器(Iterator)和可迭代对象(Iterable) 3. 使用迭代器和可迭代对象 4. 创建迭代器和可迭代对象 5. 迭代器设计模式   一 ...

随机推荐

  1. iOS原生数据存储策略

    一 @interface NSCache : NSObject Description A mutable collection you use to temporarily store transi ...

  2. 洛谷P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows 状压动归

    考场上空间开大了一倍就爆0了QAQ- Code: #include<cstdio> #include<algorithm> #include<cmath> usin ...

  3. 粘包_Client

    # from socket import *# import time# ip_port = ('127.0.0.1',8080)# back_log = 5# buffer_size = 1024# ...

  4. 谈 instanceof 和 typeof 的实现原理

    typeof: js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息

  5. Unity的Json解析<一>--读取Json文件

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/50373558 作者:car ...

  6. SpringBoot下支付宝接口的使用

    SpringBoot下支付宝接口的使用 前期准备: 参考之前写过的 支付宝接口引入servlet版本 Jar包引入: <!-- 支付宝 --> <dependency> < ...

  7. C#WIFI搜索与连接

    1.功能搜索WIFI并连接 2.所用工具及资源:VS2012 Managed Wifi API(即:引用ManagedWifi.dll文件地址:http://files.cnblogs.com/fil ...

  8. HDU 4332 Contest 4

    顶好的一道题.其实,是POJ 2411的升级版.但POJ 2411我用的插头DP来做,一时没想到那道题怎么用状态DP,于是回头看POJ 2411那一道的状态DP,其实也很简单,就是每一行都设一个状态, ...

  9. [Angular] Fetch non-JSON data by specifying HttpClient responseType in Angular

    By default the new Angular Http client (introduced in v4.3.1) uses JSON as the data format for commu ...

  10. magento megatron主题加入中文

    magento的megatron默认不支持中文,全部我们须要在它的本地化目录中加入中文的cvs文件,加入方法例如以下: 1.切换至 app ▸ design ▸ frontend ▸ megatron ...