应用层协议:HTTP

本文介绍了URL的概念和组成,详细讲解了HTTP协议,包括消息结构、请求与响应、工作过程,以及常见的请求方式GET和POST,HTTP状态码和Header。还通过实例展示了HTTP服务器的工作,并对比了HTTP与HTTPS的区别。
摘要由CSDN通过智能技术生成

URL的概念与组成

浏览某个网页时,很重要的是要知道某个网页的URL(统一资源定位符Uniform Resource Locator)

以 https://www.baidu.com/index.php 为例:
在这里插入图片描述

通过URL的组成,可以看到当我们在浏览器中输入URL时,
其中的域名会被提取出来,并用DNS服务将其解析为IP地址。
之后就进行HTTP读物,建立连接,发送请求,接收应答消息,断开连接,
最终就会在浏览器上浏览到我们想要浏览的页面。

平时俗称的 “网址” 其实就是说的 URL:
在这里插入图片描述

urlencode 和 urldecode

urldecode 就是 urlencode 的逆过程

/ ? :  等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.
比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下: 
将需要转码的字符转为16进制,然后从右到左,取4(不足4位直接处理),每2位做一位,前面加上%,编码成 %XY 格式

例:"+" 被转义成了 "%2B"

应用层协议:HTTP

全称:Hyper Text Transfer Protocol 超文本传输协议
是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)的协议。

HTTP协议工作于客户端-服务端架构为上。
浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
Web服务器根据接收到的请求后,向客户端发送响应信息。

从层次的角度看,HTTP协议是一个应用层协议;
它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。
它可以使浏览器更加高效,使网络传输减少,
不仅保证计算机正确快速地传输超文本文档,
还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

HTTP是我们浏览网页、看在线视频、听在线音乐等必须遵循的规则。
正是在这样的规则下,浏览器才能向万维网服务器发送万维网文档请求,
然后服务器会将请求的文档发送回浏览器。
在浏览器和服务器之间的请求和响应的交互,必须按照规定的格式和规则,
这些格式和规则就构成了超文本传输协议。

它所对应的传输层的协议是TCP的传输;
它所应用的传输层的端口是80号端口,另外还有一个备用端口是8080端口。

HTTP消息结构

HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。

一个HTTP"客户端"是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP的请求的目的。

一个HTTP"服务器"同样也是一个应用程序(通常是一个Web服务,如Apache Web服务器或IIS服务器等),通过接收客户端的请求并向客户端发送HTTP响应数据。

HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。

一旦建立连接后,数据消息就通过类似Internet邮件所使用的格式[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045]来传送。

HTTP协议格式

在这里插入图片描述

HTTP请求

请求格式:
在这里插入图片描述
请求报文:

请求报文(Request message)包含了四个部分的内容:
	请求行(Request line)
	头部(Headers)
	空行(A blank line)
	主体部分(Body)

请求行(Request line)包含了三部分的内容:
	Request type
	URL
	HTTP version

URL全称:Uniform Resource Locator
统一资源定位符由四部分组成:
	Method
	Host
	Port
	Path

Request message:
在这里插入图片描述
Request message 详细格式:
在这里插入图片描述
Request line:
在这里插入图片描述
HTTP请求:
在这里插入图片描述

首行: [方法] + [url] + [版本]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
Body: 空行后面的内容都是Body. Body允许为空字符串. 
      如果Body存在, 则在Header中会有一个 Content-Length 属性来标识Body的长度

HTTP响应

响应格式:
在这里插入图片描述
响应报文:

响应报文(Response message)包含了四个部分的内容:
	状态行(Status line)
	头部(Headers)
	空行(A blank line)
	主体部分(Body)

状态行(Status line)包含了三部分的内容:
	HTTP version
	Status code
	Status phrase

Response message:
在这里插入图片描述
Response message 详细格式:
在这里插入图片描述
Status line:
在这里插入图片描述
HTTP响应:
在这里插入图片描述

首行: [版本号] + [状态码] + [状态码解释]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
Body: 空行后面的内容都是Body. Body允许为空字符串. 
      如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中

HTTP工作过程:

一个HTTP的操作称为一个事物

它的工作过程分为四个步骤:
	首先客户机和服务器需要建立TCP连接,这时HTTP开始工作了;
	计算机系统中有一个专门为HTTP开放默认端口:80端口,
	还有一个备用的8080端口,主要用于万维网传输信息的协议;
	
	第二步当连接建立以后,客户机会发送一个请求给服务器,
	请求具有专门的请求格式和请求报文,
	请求的格式是统一资源定位符URL;
	
	第三步是服务器接到请求以后,给予的相应的响应信息;
	与请求类似,应答也有专门的格式与响应报文;
	
	最后一步,当客户端收到服务器所返回的信息,
	通过浏览器显示在用户的显示屏,接着客户机与服务器断开连接;
	如果在这个过程当中,某一个步骤出现了错误,
	那么产生错误的信息,将返回到客户端。

对应用户来说,这些过程是由HTTP自己完成的。
用户只要用鼠标点击,等待信息显示浏览即可。
所以用户能够看到的就是,在浏览器中间输入了你的对应的网页地址,
那么网页就显示在你的面前了。

步骤一:
首先客户机和服务器需要建立连接,这时HTTP开始工作了;
在这里插入图片描述
步骤二三:
第二步当连接建立以后,客户机会发送一个请求给服务器;
第三步是服务器接到请求以后,给予的相应的响应信息;
在这里插入图片描述
步骤四:
最后一步,当客户端收到服务器所返回的信息,
通过浏览器显示在用户的显示屏,接着客户机与服务器断开连接;
如果在这个过程当中,某一个步骤出现了错误,
那么产生错误的信息,将返回到客户端。
在这里插入图片描述

HTTP的工作究竟是如何完成的?

在双方建立连接之前,首先要知道对方的地址,那么怎样才能知道对方的地址呢?
就要通过DNS服务

第一步是浏览器分析超链接,超链接中的域名被提取出来,
通过DNS服务得到对应的IP地址;

第二步,浏览器向DNS请求解析这个域名所对应的IP,
当得到这个IP地址以后,双方就可以开始建立连接的工作了;

第三步,双方之间可以建立起TCP的连接。

如下图:
在这里插入图片描述

HTTP是应用层的服务,那么在传输层它依靠的是一个可靠的面向连接的传输,TCP的传输。
TCP的传输在80端口或者8080这个端口完成,双方建立起连接以后可以进行下一步的工作。

下一步浏览器发出HTTP请求报文,
请求报文里面含有这样一个文件命令 GET/chn/yxsz/index.htm  
意思是:希望得到chn文件夹下的yxsz文件夹下index.htm文件,
这实际上就是我们用户所需要的对应的网页文件。

当服务器收到HTTP的请求报文以后,
会按照这个路径到对应的文件夹下,取得对应的index.htm文件,
接着把这个文件组织到它的报文当中,反馈给我们的浏览器。
浏览器进行接收以后,会检查报文是否完整,
如果完整,双方之间的数据传输就完成了。
随后TCP连接可以被释放。

整个的TCP/IP三次握手结束以后,
HTTP协议还会在浏览器这一端对响应报文进行一个文件提取的工作。
它会将传过来的index.htm这个文件,按照超文本的格式在屏幕上显示出来,
所以用户这时就可以看到网页的全部内容了。

在这里插入图片描述
在这里插入图片描述

HTTP协议包括哪些请求?

在这里插入图片描述

GET:请求读取由URL所标志的信息。
POST:给服务器添加信息。
PUT:在给定的URL下存储一个文档。
DELETE:删除给定的URL所标志的资源。

两种常用的请求方式

在客户端发送请求时,有这两种常用的请求方式:GETPOST

GET方式:

是以实体的方式得到由请求URL所指定资源的信息,
如果请求URL只是一个数据产生过程,
那么最终要在响应实体中返回的是处理过程的结果所指向的资源,
而不是处理过程的描述。

POST方式:

用来向目的服务器发出请求,要求它接受被附在请求后的实体,
并把它当作请求队列中请求URL所指定资源的附加新子项,
POST被设计成用统一的方法实现下列功能:
	1.对现有资源的解释;
	2.向电子公告栏、新闻组、邮件列表或类似讨论组发信息;
	3.提交数据块;
	4.通过附加操作来扩展数据库。

可以看出,GET是向服务器发索取数据的一种请求,
而POST是向服务器提交数据的一种请求,要提交的数据位于信息头后面的实体中。

POST 与 GET 的区别:

1)Get是从服务器上获取数据,Post是向服务器传送数据。
2)Get是把参数数据队列加到提交表单的Action属性所指向的URL中,
   值和表单内各个字段一一对应,在URL中可以看到。
3)Get传送的数据量小,不能大于2KB;
   Post传送的数据量较大,一般被默认为不受限制。
4)根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。
   I.安全的:意味着该操作用于获取信息而非修改信息。
     换句话说,GET请求一般不应产生副作用。
     就是说,它仅仅是获取资源信息,就像数据库查询一样,
     不会修改,增加数据,不会影响资源的状态。
   II.幂等的:意味着对同一URL的多个请求应该返回同样的结果。

HTTP 的状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。
当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。
在这里插入图片描述
比较详细的HTTP状态码列表

最常见的状态码:
200(OK), 404(Not Found), 403(Forbidden), 
302(Redirect, 重定向), 504(Bad Gateway)

设置 HTTP 状态代码的方法:

方法描述
public void setStatus ( int statusCode )该方法设置一个任意的状态码。setStatus 方法接受一个int(状态码)作为参数。如果您的反应包含了一个特殊的状态码和文档,请确保在使用 PrintWriter 实际返回任何内容之前调用 setStatus。
public void sendRedirect(String url)该方法生成一个 302 响应,连同一个带有新文档 URL 的 Location 头。
public void sendError(int code, String message)该方法发送一个状态码(通常为 404),连同一个在 HTML 文档内部自动格式化并发送到客户端的短消息。

HTTP 常见 Header

Content-Type: 数据类型(text/html等) 
Content-Length: Body的长度
Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上; 
User-Agent: 声明用户的操作系统和浏览器版本信息;
referer: 当前页面是从哪个页面跳转过来的;
location: 搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

HTTP Content-type

列举实例:

使用GET来传递数据的实例:
客户端请求:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

服务端响应:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

输出结果:

Hello World! My payload includes a trailing CRLF.

Http Server

// 简易版的http server v1 + 多线程 + 手动构建 response,
// 展示 302 307 404 效果

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {

    /*
    端口号
     */
    private static final int PORT=9999;

    /*
    统一编码
     */
    private static final String CHARSET="UTF-8";

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket=new ServerSocket(PORT);
        ExecutorService POOL= Executors.newCachedThreadPool();
        try{
            while(true){
                Socket socket=serverSocket.accept();
                POOL.submit(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            BufferedReader reader=new BufferedReader(
                                    new InputStreamReader(socket.getInputStream()));

                            // 解析Http请求行
                            String httpLine=reader.readLine();
                            System.out.println("==="+httpLine);
                            String[] httpLineArray=httpLine.split(" ");
                            String requestMethod=httpLineArray[0];
                            String requestUri=httpLineArray[1];
                            String requestVersion=httpLineArray[2];

                            // 解析请求头
                            String requestHeader;
                            Map<String,String> headers=new HashMap<>();
                            while((requestHeader=reader.readLine())!=null && requestHeader.length()!=0){
                                String[] headerArray=requestHeader.split(":");
                                headers.put(headerArray[0].trim(),headerArray[1].trim());
                            }

                            PrintWriter writer=new PrintWriter(
                                    new OutputStreamWriter(socket.getOutputStream(),CHARSET), true);
                            String content;
                            if("/307".equals(requestUri)){
                                writer.println("HTTP/1.1 307 Temporary Redirect");
                                writer.println("Location: http://45.40.254.164");
                                content="";
                            }else if("/404".equals(requestUri)){
                                writer.println("HTTP/1.1 404 Not Found");
                                content="<h1>没有找到资源</h1>";
                            }else{
                                writer.println("HTTP/1.1 200 OK");
                                content="<h1>My Http Server</h1>";
                            }
                            writer.println("Content-Type:text/html; charset=utf-8");
                            writer.println("Context-Length:"+content.getBytes(CHARSET).length);
                            writer.println();
                            writer.println(content.toString());
                            socket.close();

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

IDEA截图:
在这里插入图片描述
http://localhost:9999/404:
在这里插入图片描述
在这里插入图片描述
http://localhost:9999:
在这里插入图片描述
在这里插入图片描述

http://localhost:9999/307:
在这里插入图片描述
CSDN 浅解:Servlet 客户端 HTTP 请求&响应

Http VS Https

http传送数据(包括账号和密码),都是明文传送,很容易被窃取或者侦听,在现有的互联网应用中,明显有不安全因素,
所以有了https,简单理解 https多一层加密解密层,在发送前加密,在收到后解密,在网络里传输的都是经过加密的数据。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值