赵小金

嗨~


  • 首页

  • 归档

四、将Vue项目改造成Nuxt项目-部署

发表于 2020-04-17 | 分类于 将Vue项目改造成Nuxt项目

正常部署流程

  1. 本地项目完成之后,npm run build完成打包工作
  2. 将项目上传至服务器
  3. 在服务器执行npm install安装
  4. 执行npm run start运行项目

问题

  1. 在本地执行npm run dev运行没有问题,但是上传服务器打包之后运行不成功。
    解决:
    大多是因为有部分代码在服务端不被识别,如window等,建议在本地自己先执行npm run start差错
  2. 在服务器安装速度比较慢,并且有可能出现网络差安装错误的情况,所以尽量不在服务端执行安装命令,需要将node_modules文件夹上传至服务器,这样又会延伸出一个问题: node_modules文件夹太大,上传时间慢,资源服务器压力大。
    解决:
    a. node_modules只安装生产环境的依赖 npm install --production
    b. 将node_modules压缩
  3. 如果每次上传都要删掉开发环境的依赖文件再去安装生产环境的依赖实现起来特别繁琐,很容易操作失误。
    解决:
    使用 shelljs插件编写一个shell脚本,每次需要修改依赖时自动执行脚本进行压缩node_modules文件夹
    实现:
    a. 编写shell.js脚本文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var shell = require('shelljs');
    if (shell.exec('rm -rf install && mkdir install && cp package.json ./install && npm install --production --prefix ./install/ && tar -zvcf node_modules.tar.gz ./install/node_modules').code !== 0) {
    shell.echo('Error: ...');
    shell.exit(1);
    }
    /**
    这个脚本实现的功能是:
    1.如果有install这个文件夹,先删掉它
    2.创建一个install文件夹
    3.将package.json文件复制一份到install文件夹中
    4.安装开发环境依赖到install中
    5.将install/node_modules文件压缩成名为 node_modules.tar.gz的压缩文件
    **/

b. 运维配置软连接指向该文件即可

三、将Vue项目改造成Nuxt项目-使用第三方插件

发表于 2020-04-16 | 分类于 将Vue项目改造成Nuxt项目

使用第三方插件

举例swiper,babel-polyfill和postcss-pxtorem插件

swiper

  1. 安装插件(略过)
  2. 我们需要在程序运行前配置好这个插件
    在plugins中新建vue-swiper.js文件:
    1
    2
    3
    4
    import Vue from 'vue'
    import VueAwesomeSwiper from 'vue-awesome-swiper/dist/ssr'

    Vue.use(VueAwesomeSwiper)

在nuxt.config.js中配置

1
2
3
plugins: [
{ src: '~/plugins/vue-swiper.js', ssr: false }
]

不支持ssr的系统,插件只在浏览器里使用的话,需要加ssr:false属性

babel-polyfill

  1. 安装插件(略过)
  2. 我们需要在程序运行前配置好这个插件
    在plugins中新建babel-polyfill.js文件:
    1
    import 'babel-polyfill'

在nuxt.config.js中配置

1
2
3
plugins: [
{ src: '@/plugins/babel-polyfill', ssr: true },
]

postcss-pxtorem

  1. 安装插件(略过)
  2. 在nuxt.config.js中配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    build: {
    extractCSS: true,
    /*
    ** You can extend webpack config here
    */
    postcss: {
    plugins: {
    'postcss-pxtorem': {
    rootValue: 37.5, //默认根目录字体大小(px)
    propList: ['*']
    },

    'autoprefixer': {
    overrideBrowserslist: ['Android >= 4.0', 'iOS >= 7']
    }
    }
    }
    }

自己编写插件

dialog插件

img

  1. 我们在components文件夹下新建一个组件showDialog.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    <template>
    <div class="dialogWrapper"
    v-if="show"
    @touchmove.prevent>
    <div class="content">
    <h3>{{title}}</h3>
    <p v-html='content'></p>
    <div class="btns"
    v-if="num==2">
    <button class="cancel"
    @click="cancel();complete();">{{cancelTxt}}</button>
    <button class="sure"
    @click="sure();complete();">{{sureTxt}}</button>
    </div>
    <div class="btns single"
    v-if="num==1">
    <button class="sure"
    @click="sure();complete();">{{sureTxt}}</button>
    </div>
    </div>
    </div>
    </template>
    <script>
    export default {
    name: 'showDialog',
    data () {
    return {
    show: false,
    title: '标题',
    content: '',
    num: 1,
    cancelTxt: '取消',
    sureTxt: '确定'
    }
    },
    methods: {
    cancel () {
    this.show = false
    },
    sure () {
    this.show = false
    },
    complete () {
    this.show = false
    }
    }
    }
    </script>
    <style lang="less" scope>
    .dialogWrapper {
    position: fixed;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
    top: 0;
    left: 0;
    z-index: 10000;
    .content {
    width: 299px;
    border-radius: 6px;
    background: #fff;
    position: absolute;
    overflow: hidden;
    top: 50%;
    left: 0;
    right: 0;
    margin: auto;
    transform: translateY(-50%);
    padding-top: 20px;
    h3 {
    font-size: 18px;
    font-weight: bold;
    text-align: center;
    color: rgba(3, 16, 42, 1);
    line-height: 20px;
    }
    p {
    padding: 14px 35px;
    font-size: 16px;
    text-align: center;
    color: rgba(3, 16, 42, 0.7);
    line-height: 20px;
    }
    }
    .btns {
    width: 100%;
    display: flex;
    background: #fff9fafa;
    padding-top: 2px;
    &.single {
    button {
    margin: 0;
    }
    }
    button {
    flex: 1;
    height: 50px;
    font-size: 16px;
    line-height: 18px;
    text-align: center;
    justify-content: center;
    color: rgba(3, 16, 42, 1);
    background: #fff;
    &:first-child {
    margin-right: 1px;
    }
    &:last-child {
    margin-left: 1px;
    }
    &.sure {
    font-weight: bold;
    color: rgba(0, 87, 255, 1);
    }
    }
    }
    }
    </style>
  2. 在文件夹plugins新建js文件vue-plugins.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import Vue from 'vue'
    import showDialog from '~/components/plugins/showDialog.vue'
    export default ({ app }, inject) => {
    if (process.client) {

    const DialogConstructor = Vue.extend(showDialog)

    // 生成一个该子类的实例
    const dialog = new DialogConstructor();

    // 并将此div加入全局挂载点内部
    dialog.$mount(document.createElement('div'))

    document.body.appendChild(dialog.$el)

    inject('showDialog', ({ title, content, num, sureTxt, cancelTxt, cancel, sure }) => {
    dialog.show = true
    title && (dialog.title = title)
    content && (dialog.content = content)
    num && (dialog.num = num)
    sureTxt && (dialog.sureTxt = sureTxt)
    cancelTxt && (dialog.cancelTxt = cancelTxt)
    cancel && (dialog.cancel = cancel)
    sure && (dialog.sure = sure)
    })
    }
    }
  3. 在nuxt.config.js中配置

    1
    2
    3
    4
    5
    6
    7

    /*
    ** Plugins to load before mounting the App
    */
    plugins: [
    '~/plugins/vue-plugins.js',
    ]
  4. 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    created () {
    // 单按钮
    this.$showDialog({
    title: '提交成功',
    content: '我们将尽快处理,如有其它问题请致电:010-56592180',
    sureTxt: '我知道了'
    })

    // 双按钮
    this.$showDialog({
    title: '提醒',
    content: '是否放弃已填写内容?',
    num: 2,
    sure: () => {
    // 确定
    }
    })

    this.$showDialog({
    title: '提醒',
    content: '是否放弃已填写内容?',
    num: 2,
    sureTxt: '好的',
    cancelTxt: '我再想想',
    sure: () => {
    // 确定
    },
    cancel () {
    // 取消
    }
    })
    }

二、将Vue项目改造成Nuxt项目-关于页面路由

发表于 2020-03-25 | 分类于 将Vue项目改造成Nuxt项目

路由

nuxt的路由没有router文件,nuxt的路由就是page文件夹下的文件目录

以下目录结构

1
2
3
4
5
6
7
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

Nuxt.js 生成对应的路由配置表为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}

看到上面的_slug和_id了吗,这是nuxt的动态路由,其中_slug是目录,_id是文件,动态目录下的index.vue是默认跳转的路由,这代表:

  1. http://localhost:3000/a,http://localhost:3000/b 打开的文件是 pages/_slug/index.vue
  2. http://localhost:3000/a/comments,http://localhost:3000/b/comments 打开的文件是 pages/_slug/comments.vue
  3. http://localhost:3000/users/123,http://localhost:3000/users/abc 打开的文件是 pages/users/_id.vue

动态嵌套路由

nuxt也可以在在动态路由下配置动态子路由。

假设文件结构如下:

1
2
3
4
5
6
7
8
9
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

Nuxt.js 自动生成的路由配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
router: {
routes: [
{
path: '/',
component: 'pages/index.vue',
name: 'index'
},
{
path: '/:category',
component: 'pages/_category.vue',
children: [
{
path: '',
component: 'pages/_category/index.vue',
name: 'category'
},
{
path: ':subCategory',
component: 'pages/_category/_subCategory.vue',
children: [
{
path: '',
component: 'pages/_category/_subCategory/index.vue',
name: 'category-subCategory'
},
{
path: ':id',
component: 'pages/_category/_subCategory/_id.vue',
name: 'category-subCategory-id'
}
]
}
]
}
]
}

这里注意:_category.vue与_category/同级

路由参数校验

在动态路由中可以设置参数校验,例如文章详情页的路由是http://localhost:3000/article/123456,123456是文章id,文章id永远都是数字,不可能是汉字,所以可以在pages/article/_id.vue页面校验一下参数:

1
2
3
4
5
6
export default {
validate ({ params }) {
// 必须是number类型
return /^\d+$/.test(params.id)
}
}

如果校验方法返回的值不为 true或Promise中resolve 解析为false或抛出Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。

新建error.vue页面在layouts文件夹中,在error.vue页面中可以捕获到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<not-found v-if="error.statusCode==404"></not-found>
<error-page v-else></error-page>
</div>
</template>
<script>
import notFound from '~/components/404.vue'
import errorPage from '~/components/500.vue'
export default {
props: ['error'],
components: { notFound, errorPage }
}
</script>

路由中间件

中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前。

它可以做到在打开页面或者切换路由之前,加一些判断,例如重定向之类的操作。
中间件放在middleware文件夹中,文件名就是中间件的名字(middleware/auth.js将成为 auth 中间件)
中间件的配置方式:

1
2
3
4
5
6
// nuxt.config.js
module.exports = {
router: {
middleware: 'stats'
}
}

可以再中间件中加重定向:

1
2
3
4
5
6
7
export default function ({ isHMR, redirect }) {
if (isHMR) return

if (route.fullPath == '/') {
return redirect('/all')
}
}

还可以加一些其他操作,例如将userAgent赋值给context:

1
2
3
4
5
6
7
8
export default function ({ isHMR, app, req, store, route, params, error, redirect }) {
if (isHMR) return
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent

if (route.fullPath == '/') {
return redirect('/all')
}
}

这样的话,在红框,黄框周期内就可以愉快的使用userAgent了:

1
2
3
4
5
6
7
validate (context) {
console.log(1, context.userAgent)
return true
},
asyncData (context) {
console.log(2, context.userAgent)
}

img

二、将Vue项目改造成Nuxt项目-关于页面路由

发表于 2020-03-25 | 分类于 将Vue项目改造成Nuxt项目

路由

nuxt的路由没有router文件,nuxt的路由就是page文件夹下的文件目录

以下目录结构

1
2
3
4
5
6
7
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

Nuxt.js 生成对应的路由配置表为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}

看到上面的_slug和_id了吗,这是nuxt的动态路由,其中_slug是目录,_id是文件,动态目录下的index.vue是默认跳转的路由,这代表:

  1. http://localhost:3000/a,http://localhost:3000/b 打开的文件是 pages/_slug/index.vue
  2. http://localhost:3000/a/comments,http://localhost:3000/b/comments 打开的文件是 pages/_slug/comments.vue
  3. http://localhost:3000/users/123,http://localhost:3000/users/abc 打开的文件是 pages/users/_id.vue

动态嵌套路由

nuxt也可以在在动态路由下配置动态子路由。

假设文件结构如下:

1
2
3
4
5
6
7
8
9
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

Nuxt.js 自动生成的路由配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
router: {
routes: [
{
path: '/',
component: 'pages/index.vue',
name: 'index'
},
{
path: '/:category',
component: 'pages/_category.vue',
children: [
{
path: '',
component: 'pages/_category/index.vue',
name: 'category'
},
{
path: ':subCategory',
component: 'pages/_category/_subCategory.vue',
children: [
{
path: '',
component: 'pages/_category/_subCategory/index.vue',
name: 'category-subCategory'
},
{
path: ':id',
component: 'pages/_category/_subCategory/_id.vue',
name: 'category-subCategory-id'
}
]
}
]
}
]
}

这里注意:_category.vue与_category/同级

路由参数校验

在动态路由中可以设置参数校验,例如文章详情页的路由是http://localhost:3000/article/123456,123456是文章id,文章id永远都是数字,不可能是汉字,所以可以在pages/article/_id.vue页面校验一下参数:

1
2
3
4
5
6
export default {
validate ({ params }) {
// 必须是number类型
return /^\d+$/.test(params.id)
}
}

如果校验方法返回的值不为 true或Promise中resolve 解析为false或抛出Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。

新建error.vue页面在layouts文件夹中,在error.vue页面中可以捕获到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<not-found v-if="error.statusCode==404"></not-found>
<error-page v-else></error-page>
</div>
</template>
<script>
import notFound from '~/components/404.vue'
import errorPage from '~/components/500.vue'
export default {
props: ['error'],
components: { notFound, errorPage }
}
</script>

路由中间件

中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前。

它可以做到在打开页面或者切换路由之前,加一些判断,例如重定向之类的操作。
中间件放在middleware文件夹中,文件名就是中间件的名字(middleware/auth.js将成为 auth 中间件)
中间件的配置方式:

1
2
3
4
5
6
// nuxt.config.js
module.exports = {
router: {
middleware: 'stats'
}
}

可以再中间件中加重定向:

1
2
3
4
5
6
7
export default function ({ isHMR, redirect }) {
if (isHMR) return

if (route.fullPath == '/') {
return redirect('/all')
}
}

还可以加一些其他操作,例如将userAgent赋值给context:

1
2
3
4
5
6
7
8
export default function ({ isHMR, app, req, store, route, params, error, redirect }) {
if (isHMR) return
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent

if (route.fullPath == '/') {
return redirect('/all')
}
}

这样的话,在红框,黄框周期内就可以愉快的使用userAgent了:

1
2
3
4
5
6
7
validate (context) {
console.log(1, context.userAgent)
return true
},
asyncData (context) {
console.log(2, context.userAgent)
}

img

一、将Vue项目改造成Nuxt项目-了解SSR

发表于 2020-03-25 | 分类于 将Vue项目改造成Nuxt项目

一、SSR概念

SSR
server side render 服务端渲染

客户端渲染
页面初始加载的 HTML 页面中无网页展示内容,需要加载执行Js代码,通过 js 渲染生成页面。比较代表性的为React,Vue,Angular三大前端框架的SPA(Single Page Application)应用。

服务端渲染
用户请求服务器,服务器上直接生成 HTML 内容并返回给浏览器。客户端所需要做的仅仅是html页面的展现和之后的DOM事件处理。代表为传统的JSP,PHP,ASP应用。

同构
同构这个概念存在于 Vue,React 这些新型的前端框架中,同构实际上是客户端渲染和服务器端渲染的一个整合。两端共用一套代码,只是服务端采用nodeJS执行,客户端采用JS执行;在加载首屏的时候,执行服务端代码,页面渲染和请求js同时进行。从首屏进入第二页时就不请求服务端代码了,直接执行Vue的路由跳转。
(这里首屏的概念不是首页,而是用户打开的第一页,例如:A打开司机招聘的首页,点击其中一条详情进入详情页,然后将详情页分享给B,B打开的是详情页。这里A的首屏是首页,B的首屏是详情页)

二、使用SSR的利弊

SSR的优势

  1. 更利于SEO
    爬虫只会爬取源码,不会执行网站的任何脚本(Google除外,Google等页面加载完之后再去爬取内容,所以Google的爬虫可以爬取单页面应用)
  2. 更利于首屏渲染
    首屏的渲染是node发送过来的html字符串,并不依赖于js文件了,这就会使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,首页就会有一个很长的白屏等待时间。

SSR的局限

  1. 服务端压力较大
    本来是通过客户端完成渲染,现在统一到服务端node服务去做。尤其是高并发访问的情况,会大量占用服务端CPU资源;
  2. 开发条件受限
    服务端代与客户端共用一套代码,但是执行周期不一致,写法也有略微不同
  3. 学习成本相对较高
    还需要掌握node、Koa2等相关技术。相对于客户端渲染,项目构建、部署过程更加复杂。

三、介绍NUXT

nuxt官网

nuxt的优点:

  • 基于 Vue.js
  • 自动代码分层
  • 服务端渲染
  • 强大的路由功能,支持异步数据
  • 静态文件服务
  • ES2015+ 语法支持
  • 打包和压缩 JS 和 CSS
  • HTML 头部标签管理
  • 本地开发支持热加载
  • 集成 ESLint
  • 支持各种样式预处理器: SASS、LESS、 Stylus 等等
  • 支持 HTTP/2 推送

流程图

下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 <nuxt-link>切换路由渲染页面)的流程:
image
生命周期流程图,红框内的是Nuxt的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端

  1. 红框、黄框内的周期都不存在Window,document,navigator对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    export default {
    asyncData() {
    console.log(window) // 服务端报错
    },
    fetch() {
    console.log(window) // 服务端报错
    },
    created () {
    console.log(window) // undefined
    },
    mounted () {
    console.log(window) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
    }
    }

但也不是不可以在这些周期使用客户端代码,只需要加一个判断平台的条件即可:

1
2
3
if (process.client){
// 这里执行服务端不支持的代码
}

三、开始

1、运行一个NUXT项目

1
$ npx create-nuxt-app abc

我的电脑运行这条命令慢的出奇,所以我用了另一种方式

1
2
3
$ npm install -g @vue/cli-init
// 如果已安装过vue-cli可以不用执行上面这条
$ vue init nuxt/starter abc

image
2、启动项目

1
2
3
4
$ cd abc
$ npm install
$ npm run dev
// 在浏览器里执行:`http://localhost:3000/`

这时项目中会多一个.nuxt的文件

image

3、打包

1
npm run build

这时看到.nuxt中的文件变了,并且多了一个dist文件夹(这里有一个坑,通常我们的.gitignore文件会忽略dist文件,这里要注意)
image

4、目录详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|-- .nuxt                            // Nuxt运行时自动生成,和build之后的代码
|-- assets // 资源目录 assets 用于组织未编译的静态资源如 LESS、SASS 或 JavaScript
|-- components // 用于自己编写的Vue组件,比如滚动组件,日历组件,分页组件
|-- layouts // 布局目录,用于组织应用的布局组件,不可更改。
|-- middleware // 用于存放中间件
|-- pages // 用于存放写的页面,我们主要的工作区域
|-- plugins // 用于存放JavaScript插件的地方
|-- static // 用于存放静态资源文件,比如图片
|-- store // 用于组织应用的Vuex 状态管理。
|-- .editorconfig // 开发工具格式配置
|-- .eslintrc.js // ESLint的配置文件,用于检查代码格式
|-- .gitignore // 配置git不上传的文件
|-- nuxt.config.js // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package.json // npm包管理配置文件

DNS解析

发表于 2020-01-06 | 分类于 网络原理 , 学习日记

DNS(Domain Name System)域名系统

一、域名系统

1、域名系统概述

域名系统DNS(Domain Name System)是因特网使用的命名系统,用来把便于人们使用的机器名字转换成为IP地址。域名系统其实就是名字系统。

我们都知道,IP地址是由32位的二进制数字组成的。用户与因特网上某台主机通信时,显然不愿意使用很难记忆的长达32位的二进制主机地址。即使是点分十进制IP地址也并不太容易记忆。相反,大家愿意使用比较容易记忆的主机名字。但是,机器在处理IP数据报时,并不是使用域名而是使用IP地址。这是因为IP地址长度固定,而域名的长度不固定,机器处理起来比较困难。

域名到IP地址的解析是由分布在因特网上的许多域名服务器程序共同完成的。域名服务器程序在专设的结点上运行,而人们也常把运行域名服务器程序的机器称为域名服务器。

2、因特网的域名结构

由于因特网的用户数量较多,所以因特网在命名时采用的是层次树状结构的命名方法。任何一个连接在因特网上的主机或路由器,都有一个唯一的层次结构的名字,即域名(domain name)。这里,“域”(domain)是名字空间中一个可被管理的划分。

如下例子所示:
image

这是中央电视台用于收发电子邮件的计算机的域名,它由三个标号组成,其中标号com是顶级域名,标号cctv是二级域名,标号mail是三级域名。

DNS既不规定一个域名需要包含多少个下级域名,也不规定每一级域名代表什么意思。各级域名由其上一级的域名管理机构管理,而最高的顶级域名则由ICANN进行管理。用这种方法可使每一个域名在整个互联网范围内是唯一的,并且也容易设计出一种查找域名的机制。

域名只是逻辑概念,并不代表计算机所在的物理地点。据2006年12月统计,现在顶级域名TLD(Top Level Domain)已有265个,分为三大类:
(1)国家顶级域名nTLD:采用ISO3166的规定。如:cn代表中国,us代表美国,uk代表英国,等等。国家域名又常记为ccTLD(cc表示国家代码contry-code)。
(2)通用顶级域名gTLD:最常见的通用顶级域名有7个,即:com(公司企业),net(网络服务机构),org(非营利组织),int(国际组织),gov(美国的政府部门),mil(美国的军事部门)。
(3)基础结构域名(infrastructure domain):这种顶级域名只有一个,即arpa,用于反向域名解析,因此称为反向域名。

image

OSI7层参考模型和TCP/IP5层参考模型

发表于 2020-01-06 | 分类于 网络原理 , 学习日记

一、相关名词

OSI(Open System Interconnection Model开放式系统互联模型)简称为OSI模型,由国际标准化组织提出,一个试图使各种计算机在世界范围内互连为网络的标准框架。定义于ISO/IEC 7498-1

OSI/RM(Open Systems Interconnection Reference Model)开放系统互联参考模型

ISO(International Organization for Standardization)国际标准化组织

ARP(Address Resolution Protocol)地址解析协议,是根据IP地址获取物理地址的一个协议

TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

二、七层模型

第7层 应用层

应用层与提供给用户的网络服务相关,这些服务非常丰富,包括文件传送、电子邮件、P2P应用等。应用层为用户提供了一个使用网络应用的“接口”。

第6层 表示层

表现层主要用于处理应用实体间的交换数据的语法,其目的是解决格式和数据表示的差别,从而为应用层提供一个一致的数据格式,使字符、格式等有差异的设备之间相互通信。除此之外,表现层还可以实现文本压缩、数据加密/解密、字符编码的转换等功能。这一层的功能在某些实际数据通信网络中是有应用层来实现的,而且表示层不独立存在。

第5层 会话层

会话层是指用户与用户的连接,通过在两台计算机间建立、管理和终止通信来完成对话。会话层的主要功能:在建立会话时核实双方身份是否有权参加会话;确定双方支付通信费用;双方在各种选择功能方面(如全双工还是半双工通信)取得一致,在会话建立以后,需要对进程间的对话进行管理与控制,例如,对话过程中某个环节输了故障,会话层在可能条件下必须对这个对话的数据,使数据不丢失,如不能保留,那么终止这个对话,并重新开始。在实际的网络中,会话层的功能已经被应用层所覆盖,很少单独存在。

第4层 传输层

传输层是第一个端到端的层次,也是进程到进程的层次。数据的通信表面上看是在两个主机之间进行,但实质上是发生在两个主机的进程之间。OSI参考模型的前三层可组成公共网络,被很多设备共享,并且计算机——交换结点(典型的交换结点是路由器,交换机等)、交换结点——交换结点是按照“接力”方式传送的。为了防止传送途中报文的丢失,两个主机的进程之间需要实现端到端控制。因此,传输层的功能主要包括复用/分解(区分发送和接收主机上的进程)、端到端的可靠传输、连接控制、流量控制和拥塞控制机制等。

第3层 网络层

网络层解决的核心问题是如何将分组通过交换网络传送至目的主机,因此,网络层的主要功能是数据转发与路由,在交换网络中,信息从源节点出发,要经过若干个中继节点所谓存储转发后,才能到达目的结点。这样一个包括源结点、中继结点、目的结点的集合称为从源结点到目的结点的路径。一般在两个结点之间会有多条路径选择,这种路由选择是网络层要完成的主要功能之一。当网络设备,比如路由器,从一个接口收到数据分组时,需要根据已掌握的路由信息将其转发到合适的接口并向下一个结点发送,直至送达目的结点。此外网络层还要对进入交换网络的通信量加以控制,以避免通信量过大造成交换网络性能下降。

第2层 数据链路层

数据链路层的主要功能是实现在相邻结点之间数据可靠而有效的传输,数据在物理介质内传输过程,不能保证没有任何错误发生。为了能实现有效的差错控制,就采用了一种以“帧”为单位的数据块传输方式。要采用帧格式传输,就必须有相应的帧同步技术,这就是数据链路层的“成帧”(“帧同步”)功能,包括定义帧的格式、类型、成帧的方法等。有了“帧”的存在,就可以将差错控制技术应用在数据帧中,例如,将数据码后面附加一定位数的循环码,从而实现数据链路层的差错控制功能。数据链路层还可以实现相邻结点间通信的流量控制。

第1层 物理层

物理层的主要功能是在传输介质上实现无结构比特流传输。所谓无结构比特流是指不关心比特流实际代表的信息内容,只关心如何将0、1这些比特以合适的信号传送至目的地,因此,物理层要实现信号编码功能,物理层的另一项主要任务就是规定数据终端设备(DTE)与数据通信设备(DCE)之间接口的相关特性,主要包括机械,电气,功能和规程4个方面的特性。机械特性也叫物理特性,说明硬件连接接口的机械特点,如接口的形状、尺寸、插脚的数量和排列方式等;电气特性规定了在物理连接上,导线的电气连接及有关电路的特性,如信号电平大小、接收器和发送器电路特性的说明,信号的识别、最大传输速率的说明等;功能特性说明物理接口各条信号线的用途,如接口信号线的功能分类等;规程特性指明利用接口传输比特流的全过程及各项用于传输的事件发生的合法顺序,包括事件的执行顺序和数据传输的方式,即在物理连接建立、维持和交换信息时,收发双方在各自电路上的动作序列。

三、OSI七层参考模型与TCP/IP协议

OSI七层网络模型

TCP/IP四层模型

TCP/IP五层模型

对应网络协议

应用层(Application)

应用层

应用层

HTTP、TFTP, FTP, NFS, WAIS、SMTP

表示层(Presentation)

Telnet, Rlogin, SNMP, Gopher

会话层(Session)

SMTP, DNS

传输层(Transport)

传输层

传输层

TCP, UDP

网络层(Network)

网络互联层

网络层

IP, ICMP, ARP, RARP, AKP, UUCP

数据链路层(Data Link)

网络接口层

数据链路层

FDDI, Ethernet, Arpanet, PDN, SLIP, PPP

物理层(Physical)

物理层

IEEE 802.1A, IEEE 802.2到IEEE 802.11

四、流程图

image

0.1+0.2!==0.3

发表于 2019-07-18
1
2
console.log(0.1 + 0.2 == 0.3) // false
console.log(0.1 + 0.2) // 0.30000000000000004

浮点数值的最高精度是17位小数,但是在进行算数计算式其精度远远不如整数。浮点数值计算会产生舍入误差,有一点需要明确,这是基于IEEE754数值的浮点计算的通病。
所以实际上,这里错的不是结论,而是比较的方法,正确的比较方法是使用Javascript提供的最小精度值

1
console.log(Math.abs(0.1 + 0.2 -0.3) < Number.EPSILON) // true

leetCode两数之和

发表于 2019-04-09

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let result = []
for (let i=0; i<nums.length; i++) {
let tmp = target - nums[i];
if (nums.indexOf(tmp) != -1) {
let tmp2 = nums.indexOf(tmp)
if (tmp2 === i) continue
result.push(i,tmp2)
return result
}
}
};
var nums = [3,2,4]
var target = 6
console.log(twoSum(nums, target))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
var result = [];
for (var i = 0; i < nums.length; i++){
for (var j = i+1; j < nums.length; j++){
if (nums[i] + nums[j] == target) {
result.push(i)
result.push(j)
return result
}
}
}
};
var nums = [2, 7, 11, 15]
var target = 26
console.log(twoSum(nums, target))

曼彻斯特编码与差分曼彻斯特编码

发表于 2019-01-18 | 分类于 网络原理 , 学习日记

昨天在看西安交大陈妍老师的视频中,老师说曼彻斯特编码中电平从高电平跳变到低电平是表示“1”,从低电平条跳变到高电平表示“0”,怎么跟我印象中好像不太一样,难道我记错了?
本着学知识不可以不求甚解的态度,我又查找了一下资料,咳咳,还真是我记错了,不过,在在网络工程师考试以及与其相关的资料中确实是这样规定的:位中间电平从低到高(向上)跳变表示“1”;位中间电平从高到低(向下)跳变表示“0”。而在清华大学出版的《计算机通信与网络教程》《计算机网络(第4版)》[1]却与之相反,在此我们将清华版称为标准曼彻斯编码。

曼彻斯特编码:

位中间电平从高到低跳变表示”1”
位中间电平从低到高跳变表示”0”。

差分曼彻斯特编码:

前半周期没有跳变表示”1”
前半周期有跳变表示”0”。

 差分曼彻斯特编码比曼彻斯特编码的变化要少,因此更适合与传输高速的信息,被广泛用于宽带高速网中。然而,由于每个时钟位都必须有一次变化,所以这两种编码的效率仅可达到50%左右。

a:数字信号 b:曼彻斯特编码 c:差分曼彻斯特编码
img

123

赵小金

赵小金的博客

28 日志
14 分类
9 标签
© 2022 赵小金
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4