计算机网络应用层(超详细!)

举报
幼儿园老大* 发表于 2024/07/04 12:43:04 2024/07/04
【摘要】 应用层功能在应用进程间传输报文,实现特定类型的数据交互,去执行特定的功能。HTTP 协议(超文本传输协议)负责发布和接收 HTML 页面和其他 Web 资源,即 Web 通信。底层通信通过 TCP 协议实现,默认端口号 80 。资源定位HTTP 协议通过 URL 来访问资源。URL 即 WEB 内容访问标识符,是一种具体的 URI。不仅唯一标识资源,而且还提供了定位该资源的信息。通用格式为:...

应用层功能

在应用进程间传输报文,实现特定类型的数据交互,去执行特定的功能。


HTTP 协议

(超文本传输协议)负责发布和接收 HTML 页面和其他 Web 资源,即 Web 通信。底层通信通过 TCP 协议实现,默认端口号 80 。

资源定位

HTTP 协议通过 URL 来访问资源。URL 即 WEB 内容访问标识符,是一种具体的 URI。不仅唯一标识资源,而且还提供了定位该资源的信息。

通用格式为:协议://IP地址或域名:端口号/文件路径?参数 ,如 http://localhost:443/student?id=10&name=mrjoker

连接方式

  • HTTP/1.0

默认使用短连接:访问页面时,客户端和服务器之间每次 HTTP 操作都会单独使用一次 TCP 连接,传输完毕后自动关闭。

客户端和服务器之间都会建立多个 HTTP 会话,开销较大。

  • HTTP/1.1

默认使用长连接:访问页面时,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,直到 HTML 页面调用的所有 web 资源传输完毕。

长连接会在 HTTP 响应头标注:Connection:keep-alive

但 HTTP/1.1 是串行化处理所有 web 资源请求。一旦有请求无法正常加载,后续请求就会被阻塞。

  • HTTP/2

增加了多路复用功能:让所有数据流共用同一个连接。接收到客户端 HTTP 请求后,服务器会一次性把所需要的 web 资源打包发送。

  1. 即使有请求无法正常加载,也不会影响处理其它 web 资源请求。
  2. TCP 连接在刚开始发送数据时会限制连接的最大速度,集中发送能更有效地利用 TCP 连接。

请求类型

HTTP 请求有以下四种常用类型:

  • GET:请求服务器数据,请求参数直接附在 URL 上(不够安全,仅适用于简单公开数据的请求和提交)

  • POST:向服务器提交数据,数据以表单形式提交(内容长度无上限,且不会被浏览器记录)

  • PUT:修改服务器数据(慎用)

  • DELETE:删除服务器数据(慎用)

除此之外 HTTP 协议在正式通信前还可能发出 OPTION 请求:先询问服务器当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。

主机识别

HTTP 协议是无状态协议,本身不保存请求和响应之间的通信状态。

也就是说通信过后服务器将无法相互识别客户端,因此我们必须引入其他方式让服务器记录客户端的信息。

Session & Cookie

负责记录对方主机信息,在 HTTP 通信中相互识别。cookie 保存在客户端,session 保存在服务器端。

  1. 客户端初次访问服务器时,服务端会自动创建 session 用来标识用户。然后在响应头 Set-Cookie 项向客户端返回 session ID。

  2. 客户端再次访问服务器时,会在请求头 Cookie 项向服务器发送 session ID,服务器根据 ID 查询 Session 就可以识别用户。

用户和通信的详细信息通常记录在 session 中,cookie 中只保存 session ID ,以避免信息泄露。如果客户端 cookie 被禁用,就需要利用 URL 重写把 session ID 直接附加在 URL 路径上。

Token

token 和 session ID 功能相同,都用来在 HTTP 通信中识别用户,过期刷新:

  • session ID 由服务器随机生成,保存在服务器 session 中。再次访问时只需要直接比对,就可以确认客户端身份。
  • token 由服务器根据用户 ID 和时间戳经过特定算法生成,服务器不保存。再次访问时服务器需要重新计算并比对,才可以确认客户端身份。

cookie 本身不安全,浏览器中 token 除放在 cookie 外,还可以放到 localStorage 中存储。浏览器发送请求时会自动携带 session ID,但发送 token 需要手动在代码中设置。由于浏览器加载 image 标签中的地址也会发送 session ID,因此使用 token 可以有效防止 CSRF 攻击。

localStorage和sessionStorage的区别; localStorage生命周期是永久,除非用户手动清除,否则这些信息将永远存在。 sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,数据也就被清空了。


HTTPS 协议

由于 HTTP 协议使用明文在互联网传送数据,易被不法分子监听和截获。我们又引入了 HTTPS 协议取而代之,默认端口 443。

HTTPS 协议在应用层下方增加了 SSL 层,使用 TLS 协议来加密和解密数据包,这样在互联网上传送的数据将经过加密。

加密方式

  1. 建立连接后的数据交互采用对称加密:加密密钥和解密密钥相同。

  2. 建立连接时协商密钥采用非对称加密:加密密钥和解密密钥不同,两个密钥互相能解密对方的加密内容。

    服务器会公开一个非对称加密密钥(公钥),并保留一个非对称加密码密钥(私钥)。

证书认证

服务器公钥由数字认证机构 CA 统一认证。CA 会用自己的私钥加密服务器公钥和相应信息,生成数字证书。在客户端向 CA 查询时将证书发送给客户端核对。

CA 根证书(包含公钥)存储在用户的浏览器中,访问网址时会自动比对服务器公钥。

  1. 客户端向服务器发送信息:请求连接,说明自己支持的加密算法,并给出随机数 A。
  2. 服务器向客户端发送信息:同意连接请求,确认合适的加密算法,并给出数字证书和随机数 B。
  3. 客户端向 CA 核对数字证书,确认有效后得到服务器公钥。

建立连接

  1. 客户端向服务器发送公钥加密信息:给出随机数 C。
  2. 服务器通过私钥解密信息,对信息 Hash 得到数字签名;然后向客户端发送私钥加密信息:返回数字签名。
  3. 客户端通过公钥解密信息,核对数字签名,确认服务器收到随机数 C。

之后双方就可以按照约定的对称加密方法,使用三个随机数生成的密钥进行数据交互。


HTTP 通信

Java 程序执行 HTTP 通信的类定义在 java.net 包内,使用时需进行导入。

基本通信方式:创建连接对象 》设置连接参数和请求属性 》建立连接并发送请求 》读取响应内容 》关闭连接

创建连接对象

  • URL 类:标记定向资源所在位置,如果格式错误则抛出 IOException

  • URLConnection 类:读取和写入 URL 类定向的资源,在 HTTP 协议中常用 HttpURLConnection 子类。

URL myUrl = new URL("https://www.baidu.com");
HttpURLConnection myCon = (HttpURLConnection)myUrl.openConnetcion();Copy to clipboardErrorCopied

配置连接

设置请求参数


myCon.setRequestMethod("POST");         // 设置连接方法(默认使用GET)

myCon.setDoInput(true);                 // 允许进行字符流输入: myCon.getInputStream().read();
myCon.setDoOutput(true);                // 允许进行字符流输出: myCon.getOutputStream().write();

myCon.setRequestMethod(1000);           // 设置最长建立连接时间,若超时则抛出 SocketTimeoutException
myCon.setRequestMethod(1000);           // 设置最长数据读取时间,若超时则抛出 SocketTimeoutExceptionCopy to clipboardErrorCopied

设置请求属性

// 设置版本
myCon.setRequestProperty("version", "1.2.3");            
// 设置浏览器类型(常用于爬虫伪装)
myCon.setRequestProperty("user-agent", "Mozilla/5.0 (compatible;  Windows NT 5.1;SV1)");
// 设置发送文本类型
myCon.setRequestProperty("Content-Type", "application/json;charset=utf-8");Copy to clipboardErrorCopied

连接并发送请求

  • connect 方法:建立连接并发送请求.
  • getOutputStream 方法:关闭输出流时自动建立连接并发送输出流请求.

myCon.connect();

OutputStreamWriter out = new OutputStreamWriter(myCon.getOutputStream());
out.write(str);                  
out.close();Copy to clipboardErrorCopied

获取响应数据

获取响应头信息

myCon.getResponseCode();        // 获取响应码(200为连接成功,404为未找到)
myCon.getHeaderField();         // 获取响应头字段
Copy to clipboardErrorCopied

获取响应内容

  • getContent 方法:获取响应内容。
  • getInputStream 方法:输入流获取响应内容,响应表明发送了错误则抛出 IOException
myCon.getContent(); 

BufferedReader in = new BufferedReader(new InputStreamReader(myCon.getInputStream()));
while ((str = in.readLine()) != null) {
    System.out.println(str);
}
in.close();Copy to clipboardErrorCopied

关闭连接

myCon.disconnect();Copy to clipboardErrorCopied

HTTP 通信用例


// 网络爬虫
public class WebCrawler{
    public static void getHttpJson(int i) {
        try {
            //配置URL
            URL myUrl = new URL("https://static-data.eol.cn/www/school/"+ i + "/info.json");
            //配置连接
            HttpURLConnection myCon = (HttpURLConnection) myUrl.openConnection();
            myCon.setRequestProperty("user-agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            myCon.setConnectTimeout(10000);
            myCon.setReadTimeout(1000);
            //建立连接
            myCon.connect();
            //如果连接成功
            if (myCon.getResponseCode() == 200) {
                System.out.print("ID" + i + "的数据读取成功,数据内容:");
                //读取返回数据
                InputStream in = myCon.getInputStream();
                int cnt = in.available();
                byte[] b = new byte[cnt];
                in.read(b);
                String str = new String(b);
                //输出返回数据
                System.out.println(str);
            }else{
                System.out.println("ID" + i + "的数据读取失败,代码:" + myCon.getResponseCode());
            }
        } catch (MalformedURLException e) {
            System.out.println("URL错误,无法查找到资源。");
        } catch(SocketTimeoutException e){
            System.out.println("ID" + i + "的数据访问连接超时。");
        } catch (IOException e) {
            System.out.println("发送的请求存在错误,资源拒绝访问。");
        }
        return;
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。