zoukankan      html  css  js  c++  java
  • 请求响应原理以及HTTP协议

     1. 服务器端基础概念

    1.1 网站的组成

    网站应用程序主要分为两大部分:客户端和服务器端

    客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序,使用HTML、css、JavaScript构建

    服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑

    1.2 Node网站服务器

    能够提供网站服务的机器就是网站服务器,能够接收客户端的请求,能够对请求作出响应

    1.3 IP地址

    互联网中设备的唯一标识

    IP:Internet Protocol Address,互联网协议地址

    1.4 域名

    由于IP地址难以记忆,产生了域名的概念,域名就是平时上网时用的网址

    虽然在地址栏中输入的是网址,但是最终还是会将域名转换为ip才能访问到指定的网站服务器

    1.5 端口

    端口是计算机与外界通讯交流的出口,用来区分服务器电脑中提供的不同服务

    同一台服务器电脑上,可以提供不同的服务,比如web服务、邮件服务等等

    1.6 URL 

    统一资源定位符,URL

    传输协议://服务器IP或域名:端口/资源所在位置标识

    http://www.itcast.cn/news/2018018/09152238514.html

    但在平时输入网址的时候我们并没有输入端口,那是因为我们访问的是服务器的web服务,默认是80端口,浏览器会自动帮我们添加上去

    http:超文本传输协议,提供了一种发布和接收HTML页面的方法 

    1.7 开发过程中客户端和服务器端说明

    在开发阶段,客户端和服务器端使用同一台电脑,即开发人员电脑

    2. 在Node.js中创建web服务器

    网站服务器实际上就是一台电脑,在这台电脑上我们要安装Node这个软件

    要使用Node这个软件创建请求对象和响应对象

    (1)需要用到系统模块http,需要先引入

    (2)下面有一个createServer方法,作用是创建服务器对象,返回值就是服务器对象

    (3)app.on('第一个参数', '第二个参数')

    第一个参数是事件的名称,比如request

    第二个参数是事件处理函数,当请求来的时候就会执行这个处理函数,函数中有两个参数,req和res

    req是请求对象,存储了请求相关的一些信息,比如请求地址、请求ip

    res是响应对象,使用这个对象下面的一些方法对客户端发来的请求做出响应

    (4)这个服务器需要监听一个端口才能对外界的请求作出响应,才能向外界提供对应的服务:app.listen(端口号),一般可以写成3000,也可以写成其他端口号,只要这个端口号没有被占用即可

    // 用于创建网站服务器的模块
    const http = require('http');
    // app 对象就是网站服务器对象
    const app = http.createServer();
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
    // 结束这次请求,并响应了括号中的内容 res.end(
    '<h2>hello,user</h2>'); }); // 监听端口 app.listen(3000); console.log('网站服务器启动成功');

    访问本机的服务器:域名:端口号   localhost:3000   (代表想要访问本机上3000端口提供的服务)

    3. HTTP协议

    3.1 HTTP协议的概念

    超文本传输协议(HyperText Transfer Protocol, 缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准

    3.2 报文

    在http请求和响应的过程中传递的数据块就叫报文,包括要传送的数据考核一些附加信息,并且要遵守规定好的格式

    3.3 请求报文

    1. 请求方法

    • GET     请求数据
    • POST   发送数据

    2. 请求地址

    • req.headers 获取请求报文  
      req.headers['accept']   获取报文具体的某一项
    • req.url   获取请求地址
    • req.method   获取请求方法
        // 获取请求地址
        // req.url
        // console.log(req.url);
        // 根据客户端请求地址的不同,服务器端响应不同的内容
        if (req.url == '/index' || req.url == '/') {
            res.end('welcome to homepage');
        } else if (req.url == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('not found');
        }
        // 获取请求报文信息
        // req.headers
        console.log(req.headers);
        // 获取某一项的具体信息
        console.log(req.headers['accept']);
    
        // 获取请求方式
        // console.log(req.method);
        if (req.method == 'POST') {
            res.end('post')
        } else if (req.method == 'GET') {
            res.end('get')
        }

    3.4 响应报文

    1. HTTP状态码

    • 200 请求成功
    • 404 请求的资源没有被找到
    • 500 服务器端错误
    • 400 客户端请求有语法错误
    // 设置状态码
    res.writeHead(500);

    2. 内容类型

    • text/html
    • text/css
    • application/javascript
    • image/jpeg
    • application/json
    res.writeHead(200, {
            'content-type': 'text/html;charset=utf-8'
        });

    如果没有设置content-type这一项,就会默认设置为纯文本,如果响应的内容里面有HTML标签就不会显示出来,全部以纯文本的形式显示

    res.end('<h1>welcome to homepage</h1>');

    比如上面这行响应,会连标签一块显示出来,如果把content-type设置为text.html,他就可以正确显示为一级标题

    charset=utf-8  作用是将文字正常显示,如果不写就会显示为乱码

    4. HTTP请求与响应处理

    4.1 请求参数

    客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器,比如登录操作

    4.2 GET请求参数

    参数被放置在浏览器地址栏中:例如:

    参数获取需要借助系统模块url,url模块用来处理url地址

    const url = require('url');
    //
    返回一个对象,把url的各个部分以对象的形式返回 // 参数一:要解析的url地址 // 参数二:将查询的参数解析成对象形式 true/false url.parse(参数一, 参数二)

    如果输入的网址是 http://localhost:3000/index?age=20&username=ctt 

        url.parse(req.url, true)

    返回以下内容:

    Url {
      protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: '?age=20&username=ctt',
      query: [Object: null prototype] { age: '20', username: 'ctt' },
      pathname: '/index',
      path: '/index?age=20&username=ctt',
      href: '/index?age=20&username=ctt'
    }

    通过下面的代码就可以解析出url中携带的参数

    url.parse(req.url, true).query

    如果我们使用 req.url来判断不同地址相应的的内容,如果携带了参数,根绝我们下面写的判断就会找不到匹配的地址,就会响应not found

    if (req.url == '/index' || req.url == '/') {
            res.end('welcome to homepage');
        } else if (req.url == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('not found');
        }

    这个时候我们就可以使用url对象中的pathname

    使用解构赋值的方式获取到query和pathname,进而进行判断

    // http://localhost:3000/index?age=20&username=ctt
    let { query, pathname } = url.parse(req.url, true); // 解构赋值
    
    // 获取请求参数
    console.log(query.age);
    console.log(query.username);
    
    // 获取请求路径
    if (pathname == '/index' || pathname == '/') {
            res.end('<h2>welcome to homepage回家</h2>');
        } else if (pathname == '/list') {
            res.end('welcome to listpage');
        } else {
            res.end('not found');
        }

    4.3 POST请求参数

    • post请求参数被放在了请求报文(form data)中,get请求参数放在了url地址栏中
    • 获取post参数需要使用data和end事件
    • 使用querystring系统模块将参数转换为对象格式
    // 用于创建网站服务器的模块
    const http = require('http');
    // app 对象就是网站服务器对象
    const app = http.createServer();
    // 处理请求参数模块
    const querystring = require('querystring');
    
    // 当客户端有请求来的时候
    app.on('request', (req, res) => {
        // post 参数是通过事件的方式接受的
        // data  当有请求参数传输的时候就会触发data事件
        // end  当请求参数传递完成以后就会触发end事件
        // post参数在理论上是可以无限的,post请求参数不是一次就接收完的
    
        //  由于不是一次传递完的,需要把每次传递的参数拼接起来
        let postParams = '';
        // params 当前传递过来的参数
        req.on('data', params => {
            postParams += params; // 这里的postParams是一个字符串
        });
        req.on('end', () => {
            // 通过querystring.parse()将字符串转换为了对象格式
            console.log(querystring.parse(postParams)); 
    
        });
        res.end('ok');
    });
    // 监听端口
    app.listen(3000);
    console.log('网站服务器启动成功');

    4.4 静态资源

    服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、images文件

    4.5 动态资源

    相同的请求地址不同的响应资源,这种资源就是动态资源

    const http = require('http');
    const url = require('url');
    const path = require('path');
    const fs = require('fs');
    const mime = require('mime');
    
    const app = http.createServer();
    
    app.on('request', (req, res) => {
        // 获取不带参数的请求路径
        let pathname = url.parse(req.url).pathname;
    
        // 当地址栏中没有输入文件时,默认跳转到default.html
        pathname = pathname == '/' ? '/default.html' : pathname;
    
        // 将用户的请求路径转换为实际的服务器硬盘路径
        let realPath = path.join(__dirname, 'public' + pathname);
    
        // 获取请求文件的类型
        let type = mime.getType(realPath);
    
        // 读取文件
        fs.readFile(realPath, (error, result) => {
            // 如果文件读取失败
            if (error !== null) {
                // 将中文正常显示出来,如果没有出现error是不需要写charset=utf-8的,因为HTML文件头部已经写了
                res.writeHead(404, {
                    'content-type': 'text/html;charset=utf-8'
                })
                res.end('文件读取失败');
                return;
            }
            res.writeHead(200, {
                // 如果不指定返回资源的类型,对于旧版本的浏览器可能就会出现问题
                'content-type': type
            })
            res.end(result)
        });
    });
    app.listen(3000);
    console.log('服务器启动成功');

    5. Node.js 异步编程

    5.1 同步API,异步API

    同步API:只有当前API执行完成以后,才能继续执行下一个API

    异步API:当前API的执行不会阻塞后续待拿的执行

    5.2 同步API,异步API的区别(获取返回值)

    同步API可以从返回值中拿到API执行的结果,但是异步API不可以

    5.3 回调函数

    自己定义函数让别人去调用

    5.4 使用回调函数获取异步API执行结果

     在异步API中,不能通过返回值得形式拿到执行结果,会默认返回undefined

    5.5 同步API,异步API的区别(代码执行顺序)

    同步API从上到下依次执行,前面代码会阻塞后面代码的执行

    异步API不会等待API执行完成后再向下执行代码

    5.6 Node.js中的异步API

    回调地狱的问题:

    const fs = require('fs');
    
    fs.readFile('./1.txt', 'utf8', (err, result1) => {
        console.log(result1)
        fs.readFile('./2.txt', 'utf8', (err, result2) => {
            console.log(result2)
            fs.readFile('./3.txt', 'utf8', (err, result3) => {
                console.log(result3)
            })
        })
    });

    5.7 Promise

    解决Node.js异步编程中出现回调地域的问题

  • 相关阅读:
    分析函数
    Orcal函数
    归档日志
    JSP数据交互
    JSP
    接口
    JAVA修饰符
    QuicKHit
    Java 三章错题
    Java 多态
  • 原文地址:https://www.cnblogs.com/ccv2/p/13211091.html
Copyright © 2011-2022 走看看