由于改文章有点大,部分代码格式有点问题,编辑之后博客园莫名其妙推出,有问题可以留言沟通。
 
什么是Node?
它是一个在浏览器之外可以解析和执行javascript代码的运行环 境,或者说是一个运行时平台,理论意义上就是javascript语言 在服务器端的运行环境。
由于Google V8引擎执行JavaScript的速度非常快,node作者把Chrome的v8引擎单独的移植了出来,Node对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行的更好。
基于这个引擎之 上,构建了一些底层的API,例如:文件操作,网络通信,给上层 的js提供了友好的API来供开发人员使用。  
 
验证Node是否安装成功:打开控制台CMD-->node -v --->输出当前node环境版本,就说明安装成功。
相关网站:
1、server.js文件:
var http = require('http');
http.createServer(function(req,res){
    res.writeHead(200,{'Content-Type':'text/plain'});
    res.end('Hello world \n');
}).,'127.0.0.1');
console.log("Server running at http://127.0.0.1:1337/");
执行:在控制台,当前文件夹下,node server.js
2、REPL(Read-Eval-Print-Loop)运行环境
    进入环境中: 执行 node 命令
      在控制台中输入 node 并执行后,如果在新的一行得到一个  > 提示符,就说明已经成功进入node环境中。
     退出环境:
            ctrl + c 两次     或者     执行   .exit  命令
3、Node天生就是模块化的,一个文件模块中定义的变量、函数、对象等都属于当前模块作用域。
    var foo ='bar';
    console.log(foo);    //输出 bar
    console.log(global.foo);    //输出 undefined
    global.foo=foo;
    console.log(global.foo);    //输出 bar 
    通过给 global 全局对象添加属性可以实现变量共享,但是不推荐使用;可以使用 module.exports 或者 exports.属性 将内容暴漏出去供其他文件使用(暴漏出去的是个对象)。
4、JS文件中指定静态路径问题
     加载图片等文件时无论在哪个js文件中写,路径都是根据当前页面来写的。
5、node.js特性
    事件驱动    (event-driven)
    非阻塞 I/O 模型    (non-blocking I/O model )
    轻量、高效    (lightweight and efficient)
    node.js是什么?
        构建与Chorme V8 引擎之上的,JS运行时。包生态系统    (package ecosystem),npm(是个管理node.js资源的系统)是世界上最大的开源库生态系统
6、node必须要在终端环境下才能执行。
7、path环境变量
    可以实现在终端中打开一个可执行文件
    快速在终端中打开:shift + 鼠标右键-->在此处打开命令窗口-->输入要打开的文件名
    实现在任意地方打开某一文件:
        首先:我的电脑--右键属性--高级系统设置--系统属性--高级--环境变量
        用户变量---PATH(如果没有可以新建)--PATH变量值路径与路径之间用英文逗号分隔。
8、console,log(__dirname)   当前文件模块所属目录的绝对路径
     console.lgo(__filename)    当前文件模块的绝对路径
    一般用于操作文件时用来进行绝对路径拼接                                                                                                                                                                                                                                                                                                                                                                                                                                
9、模块的缓存:
    对于同一个模块标识,node在第一次加载完成之后就会缓存该模块,下次继续加载该模块的时候直接从缓存中拿。
    模块的加载:
    模块可以被多次加载,但是只会在第一次加载的时候运行一次,然后被缓存:目的是为了提高性能
    nodejs模块加载的顺序是同步进行的(SeaJS中是预加载,懒执行)
    node在执行到require的时候,才会同步的加载该文件(读取文件)
    node是按照代码出现的顺序进行加载的
    node的代码运行在服务器端
    seajs中是预先加载好所有的js文件(不执行)等到所有的js文件加载完成才开始执行
    seajs是预加载懒执行(一个文件加载成功之后并没有立即执行)
    seajs预加载是为了防止在代码中出现动态加载而导致功能无法执行或者延迟执行
10、删除当前模块的缓存:
    delete require.cache[module.filename]
------------->文件操作<--------------------------
1、文件写入--同步
    同步方式写入文件:writeFileSync('./a.txt',''今天很开心") 同步代码会按照顺序执行,有利于程序员的编程思维逻辑
    在进行文件操作的时候,如果是同步的API必须使用 try-catch 来捕获异常,防止程序因为异常退出,导致后续代码无法执行
    案例:
        var fs = require('fs');
        try{
            fs.writeFileSync('一个不存在的文件路径/a.txt',''今天很开心") 
        }catch(e){
            console.log('不好意思,文件写入失败了');
        }
2、文件写入--异步
    异步方式写入文件;writeFile('./a.txt',"今天很开心",funtion(err){......}) 异步操作不会阻止后续代码执行
    在异步操作API中是无法通过try-catch 来捕获异常的,基本上所有的异步操作 API,Node 内部都把错误对象传递给了回调函数的第一个参数
    案例:
        var fs = require('fs');
        fs.writeFile('./a.txt',"今天很开心",funtion(err){
            if ( err ) {
               console.log('不好意思,文件写入失败了');             
            }
        })
    异步代码处理异常实现原理:
        回调函数的第一个参数是默认几首错误信息,第二个参数才是真正的数据
        强调错误优先:回调函数第一个参数为上一步错误信息,通过在回调函数中判断err是否为null来检测异步操作过程是否出错
        
 
3、文件追加    
    var fs = require('fs')
    var data = ' \n 文件追加的内容 '    // 给./a.txt 文件追加data 中的内容
    fs.appendFile('./a.txt',data,function(err){
        if(err){
           return  console.log('文件追加失败')   // 使用return 的方式,出错后回调函数的代码将不再往后执行
        }
        console.log('文件追加成功')
    })
4、读取文件
    var fs = require('fs')
    fs.readFile('路径',function(err,data){
        if(err){
            return console.log('文件读取失败')
        }
        console.log(data.toString())    //  data是读取出的数据,是计算机中保存的二进制数据(十六进制)
    )
5、Nodejs中npm常用命令:
    npm(node package manager)node包管理器,主要功能:安装、卸载、更新、查看、搜索、发布等
        http://www.npmjs.com    //查询一些包以及包的一些信息
    查看是否有 npm :cmd中输入  npm -v 如果有npm版本信息,则就可以使用
    npm istall <name> -g  将nodejs的依赖包安装到全局环境中---->npm install -g less 安装less到nodejs管理包中
    npm remove <name> 移除
    npm update <name> 更新
    npm ls 列出当前安装的所有包
    npm root [-g]  查看当前包(全局)的安装路径
    npm help [install]  帮助(查看install命令的帮助)
6、模块标识可以省略后缀名
    Node会按照'.js'、'.json'、'.node' 进行查找加载
    '.js'会按照js解析器解析并执行
    '.json'会以JSON格式文本进行解析    当请求的资源文件,匹配到 .json 文件,那么就会默认通过 JSON.parse(str) 将该文件直接转换并返回转换后的对象
    '.node'会以编译后的二进制文件进行解析
7、模块的循环加载
    如果发生循环依赖,可能发生得不到完整的数据的结果:
    a.js
    console.log('a.js文件被加载')    
    exports.foo = 'aaa'
    var foo = require('./b')
    console.log(foo)
    exports.foo = 'aaaaaa'
    b.js
    console.log('.b.j文件被加载')
    exports.foo = 'bbb'
    var foo = require('./a')
    console.log(foo)
    exports.foo = 'bbbbbb'
    node.js是同步执行,sea.js是异步执行
8、require得到的是值的拷贝
    在模块中,一旦输出一个值,模块内部的变化就影响不到这个值
    a.js
    var fooModule = require('./b.js')    // require 得到的实际上指的是拷贝,如果在被加载的模块中动态修改数据值是根本不起效果的
    console.log(fooModule.foo)    // bar 
    fooModule.changeFoo()
    console.log(fooModule.foo)    // bar
    b.js
    console.log(arguments)
    var foo = 'bar'
    exports.foo = foo
    exports.changeFoo = function (){
        foo = 'baz'
        console.log(foo)    // baz
    }   
9、require实现原理:(实现:MyRequire)
    首先读取要被加载的文件模块内容(字符串(js代码))
    然后通过类似于eval的一个函数去解析和执行读取到的js字符串代码
    最后得到该代码中暴漏的 module.exports 对象接口
 
 Myrequire.js
    var fs = require('fs')
    var data = fs.readFileSync('./foo.js').toString()
    var packStr = '(function(exports,module){'+data+' return module.exports})'
    var func = eval(packStr)
    var module = {
        exports : {}
    }
    console.log(func(module.exports,module))
 foo.js
    var a = 1
    exports.a = a
10、Buffer:用来创建一个专门存放二进制数据的缓存区
       Buffer是Node原生提供的全局对象,可以直接使用,不需要 require
       Buffer与字符串之间的转换:
            buffer实例对象.toString()--->转为字符串
       Buffer支持的编码:
            ASCII
            UTF8
            UTF16LE
            UCS2(UTF16LE的别名)
            Base64  图片
            Binary
            Hex 将每个字节编译成为两个十六进制字符
       Buffer构造方法:
            new Buffer(size)
            new Buffer(str [ , encoding ] )
      Buffer实例属性--大小:
            buf.length  
      Buffer实例方法:
            buf.write()
            buf.toString() 将一个buffer二进制对象转换为字符,默认编码是utf8
       Buffer的类方法
            Buffer.inEncoding() 用来判断是否支持该编码类型
            Buffer.isBuffer() 用来判断是否是一个Buffer类型对象
            Buffer.byteLength() 用来计算一个字符串对应的编码所占用的字节大小
            Buffer.concat(数组[,totalLength])  可以将多个buffer对象拼接为一个完整的buffer对象
11、路径拼接
        var fs = require('fs')
        var path = require('path')
        //如果在终端执行的时候,node 执行命令所处的路径不是当前文件模块所属的目录,那么在读取文件的时候所指定的 相对静态资源路径 就会相对于 node 命令所处的目录,为了避免错误,我们以后在执行带有路径文件操作的时候,直接进入当前文件模块所属的目录执行,因此在操作文件路径的时候,都使用绝对路径
       //但是 require 模块标识相对路径不受 node 命令所处路径的影响
        fs.requireFile(path.join(__dirname,'b.txt'),funtion(err,data){
            if(err){
                throw err
            }
            console.log(data)
        })
12、Node调试
      使用node内置调试器:[官方调试文档](https://nodejs.org/dist/latest-v6.x/docs/api/debugger.html)
       node debug ./foo.js
       进入调试状态   debug >
       命令: help ----> 查看常用命令
                  next(简写:n)---->下一步
                  quit ---->退出调试环境
                  cont 继续下一个断点
                  repl 从调试模式进入  REPL 运行环境 (按 Ctrl + c 可以退出 RPEL 回到调试模式)
                  按下 enter 可以重复执行上一次输入的调试命令
                  watch ('my_expression') 监视变量
                  unwatch('my_expression') 取消监视变量
                  step,s - Step in 步进 
                  step,o - Step out 步出    
    使用vsc(visual studio code)调试 node
        -1、在 vsc 里面,以项目的方式打开一个目录
                单独的文件是无法进行调试的
        -2、打开要调试的js文件
        -3、在要调试的地方左边 点击 设置一个红色的断点
        -4、然后按 F5 启动调试,在弹出的提示框选择调试环境:Node.js
        -5、选择了 node.js 之后,vsc 会自动在当前项目目录下生成一个 .vscode 目录
             同时在 ' .vscode ‘ 目录下自动创建一个叫做:'launch.json' 的文件
        -6、在 'launch.json' 文件中找到 configurations 属性 下面的 program 该属性
             'program' 属性中的 ${workspaceRoot} 就表示当前项目根目录
              
                在 app.js 处修改为 该项目的启动 文件名。
        -7、配置完要调试的具体文件路径之后,按 F5 启动调试
             如果启动不成功,提示找不到要启动调试的文件,那就点击树状菜单栏中的小蜘蛛图标,切换掉调试面板,然后点击左上角 绿色的 开始调试按钮
        -8、调试就开始了
13、文件其他相关操作
    读取文件、写入文件、向文件中追加内容、获取文件信息 stat 、删除文件、验证路径是否存在、重命名文件、移动文件、监视文件变化
    获取文件信息:
        fs.stat(path,function(err,stats){
            if(err)
                throw err
            console.log(stats)    //data是一个 fs.Stats对象
        })
        stats对象属性:
              { 
                  dev: 1651831854,
  mode: 33206,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: undefined,
  ino: 13792273858845704,  //文件的唯一
  size: 362, //文件大小
  blocks: undefined,
  atime: 2016-06-14T13:06:52.483Z,  //access time 最后一次使用
  mtime: 2016-06-14T13:58:49.084Z,  // modified time 最后一次修改文件内容时间
  ctime: 2016-06-14T13:58:49.084Z,   // change time 最后一次修改文件信息的时间
  birthtime: 2016-06-14T13:06:52.244Z // birth time 文件的创建时间
 }
        stats对象的方法:
            stats.isFile()    //判断传入的path 是不是文件
            stats.isDirectory()    //判断传入的 path 是不是目录
    删除文件:
    重命名文件:
        fs.rename(oldPath,newPath,callback)    //callback 没有推荐参数
        fs.renameSync(oldPath,newPath)
    读取目录:
        fs.readdir(dirpath,function(err,files){
            if(err){
                throw err
            }
            console.log(files)
        })
    监视文件:
        //监视文件执行之后,程序会保持挂起状态,监视文件变化,当文件发生变化时执行 listener 函数
        fs.watchFile(filename [,options ] ,listener)
            options <Object>
                persistent 永久的,Boolean
                interval 间隔,Integer整数
                例如:{ persitent : true , interval 5007 } //默认5007ms后执行
            listener <Function>  当文件在任何时间被使用的时候调用
                例如:function(cuur,prev){......}    // current stat object , previous stat object
14、path对象
    var path = require('path')    //创建path对象
    方法:
        path.extname(路径)    //获取文件的扩展名部分
        path.extname('index.html')
// returns '.html'
path.extname('index.coffee.md')
// returns '.md'
path.extname('index.')
// returns '.'
path.extname('index')
// returns ''
path.extname('.index')
// returns ''
        path.dirname(路径)    //获取文件所在的目录
            path.dirname('/foo/bar/baz/asdf/quux')
            // returns '/foo/bar/baz/asdf'
        path.basename(路径[,extendname])    //获取文件名
            path.basename('/foo/bar/baz/asdf/quux.html')
            // returns 'quux.html'
            path.basename('/foo/bar/baz/asdf/quux.html', '.html')
            // returns 'quux'
        path.delimiter    //定界符
            unix:
                console.log(process.env.PATH)
                // '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'
                process.env.PATH.split(path.delimiter)
                // returns ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
            window:              
console.log(process.env.PATH)
// 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'
process.env.PATH.split(path.delimiter)
// returns ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
        path.format( pathObject )    //路径格式化,获得属性值按顺序拼接的结果
                path.format({
    dir: '/home/user/dir',
    base: 'file.txt'
});
// returns '/home/user/dir/file.txt'
path.format({
    root : "C:\\",
    dir : "C:\\path\\dir",
    base : "file.txt",
    ext : ".txt",
    name : "file"
})
// returns 'C:\\path\\dir\\file.txt'
         path.isAbsolute(路径)    //判断路径是否是绝对路径
                path.isAbsolute('//server')  // true
path.isAbsolute('C:/foo/..') // true
path.isAbsolute('bar\\baz')  // false
path.isAbsolute('.')         // false
        path.join([path1],[path2],[,.....])    //拼接路径               
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
// returns '/foo/bar/baz/asdf'    //加上两个点,表示拼接到当前目录的上级目录
path.join('/foo', 'bar', 'baz/asdf', 'quux')
// returns '/foo/bar/baz/asdf/quux
path.join('/foo', 'bar', 'baz/asdf', 'quux','.')

// returns '/foo/bar/baz/asdf/quux   //加一个点,表示拼接到当前目录

path.parse(路径)  //路径解码
path.parse('C:\\path\\dir\\index.html')
// returns
// {
//    root : "C:\\",
//    dir : "C:\\path\\dir",
//    base : "index.html",
//    ext : ".html",
//    name : "index"
// }
--------------------------------Node使用第三方包------------------------------------------
目的:使用别人做好的一些功能,然后在具体的代码的地方去加载这个包,可以辅助项目功能的开发
1、node官网--->npm-->搜索相应的包--->githup...仓库地址--->下载--->引入项目中-->找该包的入口文件:
    在该包目录下找 package.json 文件
    在 package.json 文件中,找 main 属性,main属性保存的是文件的入口模块
2、使用npm工具进行下载安装
    在当前项目目录下 npm install 包名 + 回车   安装过程必须联网
    安装成功:
        下图是安装 markdown 成功后显示的界面:
        
    安装成功后, node 会自自动在当前项目的根路径下创建一个目录叫做:node_modles ,然后把第三方包自动放到该目录下。该目录是专门用来防止第三方包的!所有内容最好不要修改!
    3、使用该包:
        使用 require 加载第三方包
        对于第三方包来说,在 require 方法的模块标识应该输入 npm install 时候的包名
4、什么是包?
     
包描述文件中的 dependencies 是一个非常重要的字段,可以和 npm 工具结合起来使用
    当我们执行 'npm install'命令的时候,npm 工具自动在当前执行命令的目录下找 package.json文件,如果找到,把里面的 dependencies 字段里面的值拿出来,然后依次下载(联网状态)
    如果想要把项目托管到 github 上,那么就不要把 node_module 目录放到源码中。对于一些第三方依赖的包让用户自己下载即可。
5、包的加载规
     对于 require 模块标识来说
        文件模块:以/  ../   / 开头的标识符、
        核心模块:不以 ./   ../   / 开头的标识符、
        特殊的文件模块即包模块:既不是文件模块标识也不是核心模块标识,但是 node.js 默认会把它当成核心模块进行加载,如果 node 在加载的过程中发现 标识符名 不是核心模块,到当前文件所属目录下找 node_modules ,目录下找有没有一个叫做 该模块标识的,如果找到了 该标识名 的子目录,那么 node 会找该子目录下的一个叫做 package.json 的文件,如果找到了 package.json 文件,那么该文件中的一个属性 main ,得到里面的值,然后根据 main 的值指定的路径进行加载(这样做的好处:用户在使用第三方包的时候再也不用关心这个包的入口模块是哪个文件了)
        如果 node 在当前目录下的 node_modules 目录下找不到,该模块标识的 目录,那么node 会自动进入上一级目录下,找上一级目录下有没有一个叫做 node_module的目录,如果找到按照上面的规则进行加载,如果找不到则继续往上查找,直到到达根路径,若还未找到则进行报错
 
6、npm的基本使用(二)
    在加载第三方包的时候最好使用:npm install 报名 --save 自动将依赖项添加到 package.json 的 dependencies 字段上(--save 可以在包名前面,也可以在包名后面)
    npm uninstall 包名 --save   卸载包,并在 dependencies 依赖上删除依赖
7、安装一些全局命令工具行
    使用 npm 也可以安装一些命令终端下的一些工具,例如类似于 npm 这样的工具
    安装方式:
        npm install http-server -g  //安装 http-server 命令行工具到全局目录下
    查看全局命令行安装的目录:
        npm root -g
8、本地安装目的是为了在代码中具体的辅助我们进行功能开发
     全局安装目的是为了把要安装的这个包当做一个全局命令行下的工具来使用
9、解决 npm 被墙的问题
     因为 npm 的镜像源都在国外,所以国外的网站......
     国内的淘宝做了一个 npm 镜像:搜索   cnpm-淘宝 npm 镜像
     安装 cnpm 到全局命令行终端下:
npm install -g cnpm --registry=https://registry.npm.taobao.org
     
     cnmp 和 npm 的命令一致
     如果不想安装 cnpm 可以自己手动指定镜像源:
     
     nrm (node registry management) 镜像源地址管理工具,它也是一个基于 node 开发的一个全局命令行工具
     
    安装完之后就可以在终端的任何路径下使用 nrm 命令来管理镜像源地
    
    使用:
        nrm 查看使用帮助
        nrm ls 显示所有可用的镜像源
        nrm current 显示当前所使用的镜像源名字
        nrm use 镜像源名称,可以用来切换镜像源地址
10、npm发布
       注册npm账号:
           npm adduser    执行该命令,依次输入用户名、密码、Email,等待注册成功即可
       因版本太低导致发布不成功:
           sudo npm install -g npm
            
       发布程序包:
           npm publish <本地路径> 
       更新程序包:
           只需要修改 package.json的版本号即可
       取消发布内容:
           npm unpublish 包名@版本号
----------------------------->文件流(处理大文件)<-----------------------------------------
使用:
    var  fs = require('fs')
    1、创建一个可读流
    var rs = fs.createReadStream(读取文件路径)
    2、创建一个可写流
    var ws = fs.createWriteStream('写入文件的路径')
    3、监听可读流的 data 事件,然后将 data 事件的回调函数中的数据写到可写流当中
    方法1:
    rs.on('data',function(chunk){
        ws.write(chunk)
    })
    方法2--管子:pipe是一个高效的数据处理方式
            rs.pipe(ws)
            
------------------------------------>FQCross Fire<----------------------------------------------
GFW(Great Firewal of China)中国国家防火墙
vpn
蓝灯lanrern:
---蓝灯官网
ShadowSocks:只是一个客户端软件
 
 
作业:
学习如何发布一个包到npm上
自学 bower(全局命令行工具)(是什么,解决什么问题,如何使用)
Bower与npm的区别:
Bower的安装和升级都会依赖于npm:npm install -g bower,bower的使用方式跟npm类似
npm主要运用于node.js项目的内部依赖包管理,安装的模块位于项目根目录下的node_modules文件内,在使用过程中主要针对后端开发(嵌套管理);
而Bower大部分情况下用于前端开发,对于CSS/JS模板等内容进行依赖管理,依赖的下载目录结构可以自定义( 扁平化管理)。
----------------------------->网络编程<-----------------------------------------
1、node只是一个可以帮助我们呢学习网络编程的一个工具,使用其他编程语言或者操作系统进行网络编程,思想都是一致的。
Node是一个面向网络而生的平台。
Node的目标是成为一个构建快速、可伸缩的网络应用平台。
每一个Node进程构成网络应用的一个节点,这就是Node的含义。Node诞生的目的就是为了更加高效得处理网络数据而诞生的。
服务器的本质目的:服务器本质就是一个计算机。
端口号是用来具体定义一个应用程序的。
2、Net:
    -1、加载net
        var net = require('net')
    -2、使用net核心模块创建一个服务器
        var server = net.createServer()    //通过调用 createServer() 方法创建一个服务器对象
    -3、设置监听客户端的连接请求事件处理
        server.on('connection',function(){
           
        })
    -4、启动服务器
        server.listen(端口号)
3、查看自己的IP地址:ipconfig    在linux和mac:ifconfig
4、Socket网络编程:
    -1、创建服务器:
    var  net = require('net')
    var server = net.createServer();   
    server.on('connection',function(socket){
        socket.on('data',function(data){
              console.log('客户端说:'+data.toString())
              socket.write('服务器对客户端说:你猜......')
        }
        socket.on('error',function(){
              console.log('有客户端异常退出了')

})

    })   
    server.listen(3030)
 //connection链接事件只有第一次 客户端与服务器端 连接成功之后调用
 //server.listen('端口号','监听的IP','回调函数其实也就是listenning事件')

//当客户端和服务器连接成功之后,服务器会把客户端的ip地址和端口号封装为一个Socket对象,传递给connection方法的回调函数的第一个参数
        //socket是一个双向流,可读可写,谁与服务器连接就是谁

        //data就是接收到的客户端的消息,接收到的数据是二进制
        //socket.write('......')向客户端发送数据
        //server.on('listenning',function(){

        //})
    -2、创建客户端
        var net = require('net')
        var client = net.createConnection({
            port : 3030,
            host : '服务器IP'    
        })
        client.on('connect',function(){
            console.log('客户端与服务器端连接成功了,可以进行通信了')
            client.write('客户端对服务器说:请问你叫什么?')    //每一次都会从 client 里面把端口号和 IP 拿出来,将消息发送出去
        })
        client.on('data',function(data){
            console.log('服务器说:'+data.toString())
        })
         //host:服务器 IP 或者是 127.0.0.1 本机回环IP,这样的话即使在没有网的情况下也能进行 客户端与服务器 的通信,这时候本机就充当 客户端与服务器 这两个角色
        //当客户端要与服务器连接通讯的时候,程序会自动为客户端分配一个端口号来与服务器通信
        //客户端与服务器端什么时候连接成功无法确定(取决于带宽和端口号等),则通过connect事件来解决连接之后再处理事件
        //data是接收到的服务器端的消息,接收到的数据是二进制
        //client.write('......') 向服务器端发送数据
5、Socket对象:
    socket.localAddress    服务器地址
    socket.localPort    服务器端口号
    socket.remoteAddress    客户端地址
    socket.remoteFmaily    客户端IP簇:IPV4/IPV6 
    socket.remotPort    客户端端口号
    socket.on('data',function(data){
        console.log(data.toString().trim())    //输出从客户端返回的数据
    })
    socket.write()    客户端连接成功后,给客户端发送内容
    scoket.on('error',function(){
        console.log('有客户端异常退出了')    
    })    //当客户端异常的时候触发
6、全局命令行工具---解决每次编写完服务器程序之后都要重启服务器的问题
    nodemon-----基于node.js的全局命令行工具
    安装:npm install -g nodemon
    使用:nodemon example.js
7、Global
    process就是当前运行的程序或者说进程
    获取用户输入:
        process.stdin.on('data',function(data){
            console.log(data.toString().trim())    //data就是获取到的用户输入的内容
        })
    //stdin(standard input)标准输入
    process.version    进程的版本号
    process.title    进程执行的窗口名称
8、在地址栏输入网址后页面是如何呈现的?
9、HTTP协议:
    基于传输层之上的应用层的一种协议。
    
    协议:就是约定出来双方共同遵守的内容。
    OSI:(Open System Interconnection Reference Model)模型:开放式系统互联通信参考模型,简称OSI模型
        一种概念模型,由国际化标准组织ISO提出。
        一个试图使各种计算机再世界范围内互联网通信的标准框架、标准规范。
    数据传输:
应用层
    HTTP
传输层
    
网络层
数据链路层
物理层
10、安装 curl 工具
    curl -v 地址:端口号    //
11、web网络编程
    请求报文:
    响应报文:
    
12、浏览器本质.js
       var net = require('net')
       var server = net.createServer()
       server.on('connection',function(socket){
            socket.on('data',funtion(data){
                console.log(data.toString())
                socket.write('HTTP/1.1 200 OK \n\n hello world')    //写请求头
                scoket.end()    //结束响应
            })
       })
    在 浏览器 中查看;使用 curl 查看具体内容
13、http
    var http = repuire('http')
    var server = http.createServer()    //创建一个 HTTP 服务器(其实就是一个 Socket 服务器)       
    //request 就是一个可读流,用来 获取 当前与服务器连接的客户端的一些请求报文数据
    //response 就是一个可写流,用来给 客户端 Socket发送消息的,或者用来发送响应报文的
    server.on('request',function(){    
        //console.log(有客户端进来了')
        //对于 HTTP 请求响应模型来说,他们的每次请求和响应式一次性的。也就是说每次请求都必须结束响应
        //HTTP 发送响应数据的时候,HTTP 服务器会自动把数据通过 HTTP 协议包装为一个响应报文的对象
        response.write('hello world')
        //在结束之前可以多次向 客户端 发送数据
        response.write(''end)
        //响应结束后 必须有结束响应的标志,否则浏览器会认为还没有把数据发送完成,就不能渲染出来
        response.end()
        //在一次HTTP请求响应模型中,当结束了响应,就不能继续发送数据,否则就会出现错误1提示的 45 5错误
    })
    server.listen(端口号,function(){
        console.log('server is listening at port 3000')           
    })
    错误1:
    

 ------通过请求路径访问:
    server.on('request',function(request,response){
        var url = request.url
        if(url ==='/' ){
            response.end('hello')
        }else if(url === '/login'){
            response.end('helo login')
        }else{
            response.end('404 not Fond!')
        }
    })
-------读取页面:
    var fs = require('fs)
    var path = require('path')
    server.on('request',function(request,response){
        var url = request.url
        if(url ==='/' ){
            fs.readFile(path.join(__dirname,'....html'),'utf-8',function(err,data){
                if(err){
                    throw err
                }
                response.end(data)
            })
        }else if(url === '/login'){
            ...
        }else{
            response.end('404 not Fond!')
        }
    })    
--------node 的 HTTP 模块天生就不具备处理静态资源请求的能力???
        传统的 Apache 、tomcat、IIS 默认都为使用者处理了静态资源请求
------处理静态资源请求
    var http = require('http')
    var fs = require('fs')
    var path =require('path')
    var server = http.createServer()
    server.on('request',function(req,res){
        var url = req.url    //端口号后面的请求文件的路径名
        var fullpath = path(__dirname,url)
        if(url==='/'){    //当没有输入路径的时候,默认让用户访问一个地址
            fullpath = path(__dirname,'默认访问路径')
        }
        fs.readFile(fulPath,function(err,data){
            if(err){
                //在进行web 开发的时候,如果发生错误,可以直接把该错误消息输出给 客户端
                return res.end(err.message)    
            }
            res.end(data)
        })
    })
    server.listen(端口号,function(){
        console.lgog('服务已经启动......')
    })
-----------------------------------------------------------------------------
 查看文件对应的 ContentType 类型
根据不同 url 处理不同的内容

 
 
表单的提交处理:
如果表单中有上传的文件,必须指定 enctype="multipart/form-data";
没有指定 enctype 的情况下,可以在后台使用 qstring.parse(data) 处理表单以 post 方式传递过来的数据为 JSON 字符串。
处理以 post 方式提交文件的表单,可以使用社区的一个包:formidable    //查看 npm 官网,查看包的例子
    安装包:npm install --save formidable
    查看并使用包的相关方法
表单内容提交成功后跳转:
res.writeHead(302,{'Location:'跳转的地址''})
res.end()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

模块化开发(三)---通过node.js学习模块化开发的更多相关文章

  1. 快速使用node.js进行web开发

    首先关于node.js的学习,这里推荐一本比较好的教程,nodejs web开发指南,该书通俗易懂地将node.js语言特性讲解完之后,又从一个项目角度带领读者使用node.js学习web开发.相信这 ...

  2. 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)

    一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须按照一定的格式编写.AMD,CMD,CommonJS 是目前最常用的三种模块化书写规范.  1.AMD(Asy ...

  3. 【 js 模块加载 】【源码学习】深入学习模块化加载(node.js 模块源码)

    文章提纲: 第一部分:介绍模块规范及之间区别 第二部分:以 node.js 实现模块化规范 源码,深入学习. 一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须 ...

  4. Node.js学习笔记——Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...

  5. Node.JS 学习路线图

    转载自:http://www.admin10000.com/document/4624.html 从零开始nodejs系列文章, 将介绍如何利Javascript做为服务端脚本,通过Nodejs框架w ...

  6. node.js学习之路

    (非原创) 目录 Nodejs的介绍 15个Nodejs应用场景 Nodejs学习路线图 1. Nodejs的介绍 Node.js的是建立在Chrome的JavaScript的运行时,可方便地构建快速 ...

  7. 认识Web前端、Web后端、桌面app和移动app新开发模式 - 基于Node.js环境和VS Code工具

    认识Web.桌面和移动app新开发模式 - 基于Node.js环境和VS Code工具 一.开发环境的搭建(基于win10) 1.安装node.js和npm 到node.js官网下载安装包(包含npm ...

  8. Node.js学习系列总索引

    Node.js学习系列也积累了一些了,建个总索引方便相互交流学习,后面会持续更新^_^! 尽量写些和实战相关的,不讲太多大道理... Node.js学习笔记系列总索引 Nodejs学习笔记(一)--- ...

  9. 【入门必备】最佳的 Node.js 学习教程和资料书籍

    Web 开发人员对 Node.js 的关注日益增多,更多的公司和开发者开始尝试使用 Node.js 来实现一些对实时性要求高,I/O密集型的业务.这篇文章中,我们整理了一批优秀的资源,你可以得到所有你 ...

随机推荐

  1. Xilinx FPGA编程技巧之常用时序约束详解

    1.   基本的约束方法 为了保证成功的设计,所有路径的时序要求必须能够让执行工具获取.最普遍的三种路径为: 输入路径(Input Path),使用输入约束 寄存器到寄存器路径(Register-to ...

  2. 00-IT人士必去的10个网站

    IT人士必去的10个网站 1.Chinaunix 网址:http://www.chinaunix.net/ 简介:中国最大的linux/unix技术社区. 2.ITPub 网址:http://www. ...

  3. dutacm.club_1094_等差区间_(线段树)(RMQ算法)

    1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total ...

  4. JavaScipt30(第四个案例)(主要知识点:数组原型链上的一些方法)

    承接上文,下面是第四个案例 附上项目链接: https://github.com/wesbos/JavaScript30 const inventors = [ { first: 'Albert', ...

  5. java中的数学函数Math方法记录

    1,三角函数与属性Math.sin() -- 返回数字的正弦值Math.cos() -- 返回数字的余弦值Math.tan() -- 返回数字的正切值Math.asin() -- 返回数字的反正弦值M ...

  6. API Studio 5.1.2 版本更新:加入全局搜索、支持批量测试API测试用例、读取代码注解生成文档支持Github与码云等

    最近在EOLINKER的开发任务繁重,许久在博客园没有更新产品动态了,经过这些日子,EOLINKER又有了长足的进步,增加了更多易用的功能,比如加入全局搜索.支持批量测试API测试用例.读取代码注解生 ...

  7. KMP瞎扯一下

    什么是KMP KMP俗称看毛片算法,是高效寻找匹配字串的一个算法 百度百科 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为 ...

  8. Python学习-while循环语句

    Python 编程中 while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务.即重复性的做一件事情 语法形式如下: while 判断条件: 条件满足执行语句…… ...

  9. linux ifstat-统计网络接口流量状态

    推荐:更多linux 性能监测与优化 关注:linux命令大全 ifstat命令就像iostat/vmstat描述其它的系统状况一样,是一个统计网络接口活动状态的工具.ifstat工具系统中并不默认安 ...

  10. js中的三种弹框分别是alert(),confirm(),prompt()

    1.alert(): ①写在<script>标签中 ②括号中的内容为字符串或者整型 ③点击确认即可关闭,无返回值 2.confirm(): ①写在<script>标签中 ②括号 ...