5,I/O与网络编程

5.1I/O基础

5.1.1 java有哪几种文件拷贝方式,哪一种效率最高。

第一种,使用 java.io 包下的库,使用 FileInputStream 读取,再使用 FileOutputStream 写出。
第二种,利用 java.nio 包下的库,使用 transferTo 或 transfFrom 方法实现。
第三种,Java 标准类库本身已经提供了 Files.copy 的实现。
对于 Copy 的效率,这个其实与操作系统和配置等情况相关,
在传统的文件 IO 操作里面,我们都是调用操作系统提供的底层标准 IO 系统调用函数 read()、
write() ,由于内核指令的调用会使得当前用户线程切换到内核态,然后内核线程负责把相应的文件数据读取到内核的 IO 缓冲区,再把数据从内核 IO 缓冲区拷贝到进程的私有地址空间中去,这样便完成了一次 IO 操作。
而 NIO 里面提供的 NIO transferTo 和 transfFrom 方法,也就是常说的零拷贝实现。
它能够利用现代操作系统底层机制,避免不必要拷贝和上下文切换,因此在性能上表现比较好。

5.1.2 I/O 和NIO的区别是什么

首先,I/O ,指的是 IO 流, 它可以实现数据从磁盘中的读取以及写入。
实际上,除了磁盘以外,内存、网络都可以作为 I/O 流的数据来源和目的地。
在 Java 里面,提供了字符流和字节流两种方式来实现数据流的操作。
其次,当程序是面向网络进行数据的 IO 操作的时候,Java 里面提供了 Socket 的方式来实现。
通过这种方式可以实现数据的网络传输。
(如图)基于 Socket 的 IO 通信,它是属于阻塞式 IO,也就是说,在连接以及 IO 事件未就绪的情况下,当前的连接会处于阻塞等待的状态。
在这里插入图片描述
一旦某个连接处于阻塞状态,那么后续的连接都得等待。所以服务端能够处理的连接数量非常有限。
NIO,是 JDK1.4 里面新增的一种 NEW IO 机制,相比于传统的 IO,NIO 在效率上做了很大的化,
并且新增了几个核心组件。
Channel、Buffer、Selectors。
(如图)另外,还提供了非阻塞的特性,所以,对于网络 IO 来说,NIO 通常也称为 No-Block IO,非阻塞 IO。
也就是说,通过 NIO 进行网络数据传输的时候,如果连接未就绪或者 IO 事件未就绪的情况下,服务端不会阻塞当前连接,而是继续去轮询后续的连接来处理。
所以在 NIO 里面,服务端能够并行处理的链接数量更多。
在这里插入图片描述
IO 和 NIO 的区别,站在网络 IO 的视角来说,前者是阻塞 IO,后者是非阻塞 IO。

5.1.3 谈谈你对I/O多路复用机制的理解

IO 多路复用机制,核心思想是让单个线程去监视多个连接,一旦某个连接就绪,也就是触发了读/写事件。
就通知应用程序,去获取这个就绪的连接进行读写操作。
也就是在应用程序里面可以使用单个线程同时处理多个客户端连接,
在对系统资源消耗较少的情况下提升服务端的链接处理数量。
在 IO 多路复用机制的实现原理中,
客户端请求到服务端后,此时客户端在传输数据过程中(如图),
为了避免 Server 端在 read 客户端数据过程中阻塞,服务端会把该请求注册到 Selector 复路器上,
服务端此时不需要等待,只需要启动一个线程,通过 selector.select()阻塞轮询复路器上就绪的 channel 即可,也就是说,如果某个客户端连接数据传输完成,那么 select()方法会返回就绪的 channel,然后执行相关的处理就可以了。
在这里插入图片描述
常见的 IO 多路复用机制的实现方式有: select 、poll、epoll。
这些都是 Linux 系统提供的 IO 复用机制的实现,其中 select 和 poll 是基于轮询的方式去获取就绪连接。
而 epoll 是基于事件驱动的方式获取就绪连接。从性能的角度来看,基于事件驱动的方式要优于轮询的方式。

5.2 网络编程

5.2.1 什么是网络四元组

简单理解就是在 TCP 协议中,去确定一个客户端连接的组成要素,它包括源 IP 地址、目标 IP
地址、源端口号、目标端口号。
正常情况下,我们对于网络通信的认识可能是这样(如图)。
服务端通过 ServerSocket 建立一个对指定端口号的监听,比如 8080。 客户端通过目标 ip 和端口就可以和服务端建立一个连接,然后进行数据传输。
在这里插入图片描述
但是我们知道的是,一个 Server 端可以接收多个客户端的连接,比如像这种情况(如图)。
那,当多个客户端连接到服务端的时候,服务端需要去识别每一个连接。
在这里插入图片描述并且(如图),TCP 是全双工协议,也就是说数据允许在连接的两个方向上同时传输,因此这里的客户端,如果是反向通信,它又变成了服务端。
在这里插入图片描述
所以基于这两个原因,就引入了四元组的设计,也就是说,当一个客户端和服务端建立一个 TCP 连接的时候,通过源 IP 地址、目标 IP 地址、源端口号、目标端口号来确定一个唯一的 TCP 连接。因为服务器的 IP 和端口是不变的,只要客户端的 IP 和端口彼此不同就 OK 了。
比如像这种情况(如图),同一个客户端主机上有三个连接连到 Server 端,那么这个时候源 IP 相同,源端口号不同。此时建立的四元组就是(10.23.15.3,59461 , 192.168.8.135,8080)
其中,源端口号是每次建立连接的时候系统自动分配的。
在这里插入图片描述

5.2.2 TCP为什么要设计3次握手

关于这个问题,我会从下面 3 个方面来回答。

  1. TCP 协议,是一种可靠的,基于字节流的,面向连接的传输层协议。
     可靠性体现在 TCP 协议通信双方的数据传输是稳定的,即便是在网络不好的情况下,TCP 都
    能够保证数据传输到目标端,而这个可靠性是基于数据包确认机制来实现的。
     TCP 通信双方的数据传输是通过字节流来实现传输的
     面向连接,是说数据传输之前,必须建立一个连接,然后基于这个连接进行数据传输
  2. (如图)因为 TCP 是面向连接的协议,所以在进行数据通信之前,需要建立一个可靠的连接,TCP采用了三次握手的方式来实现连接的建立。
    所谓的三次握手,就是通信双方一共需要发送三次请求,才能确保这个连接的建立。
     客户端向服务端发送连接请求并携带同步序列号 SYN。
     服务端收到请求后,发送 SYN 和 ACK, 这里的 SYN 表示服务端的同步序列号,ACK 表示对
    前面收到请求的一个确认,表示告诉客户端,我收到了你的请求。
     客户端收到服务端的请求后,再次发送 ACK,这个 ACK 是针对服务端连接的一个确认,表示
    告诉服务端,我收到了你的请求。
    在这里插入图片描述
  3. 之所以 TCP 要设计三次握手,我认为有三个方面的原因:
     TCP 是可靠性通信协议,所以 TCP 协议的通信双方都必须维护一个序列号,去标记已经发送出去的数据包,哪些是已经被对方签收的。而三次握手就是通信双方相互告知序列号的起始值,为了确保这个序列号被收到,所以双方都需要有一个确认的操作。
     TCP 协议需要在一个不可靠的网络环境下实现可靠的数据传输,意味着通信双方必须通过某种手段来实现一个可靠的数据传输通道,而三次通信是建立这样一个通道的最小值。当然还可以四次、五次,只是没必要浪费这个资源。
     防止历史的重复连接初始化造成的混乱问题,比如说在网络比较差的情况下,客户端连续多次发送简历连接的请求,假设只有两次握手,那么服务端只能选择接受或者拒绝这个连接请求,但是服务端不知道这次请求是不是之前因为网络堵塞而过期的请求,也就是说服务端不知道当前客户端的连接是有效还是无效。以上就是我对这个问题的理解。

5.2.3 Cookie和Session有什么区别

我先解释一下 Cookie,它是客户端浏览器用来保存服务端数据的一种机制。
当通过浏览器进行网页访问的时候,服务器可以把某一些状态数据以 key-value 的方式
写入到 Cookie 里面存储到客户端浏览器。
然后客户端下一次再访问服务器的时候,就可以携带这些状态数据发送到服务器端,服务端可以根据 Cookie 里面携带的内容来识别使用者。
Session 表示一个会话,它是属于服务器端的容器对象,默认情况下,针对每一个浏览器的请求。
Servlet 容器都会分配一个 Session。
Session 本质上是一个 ConcurrentHashMap,可以存储当前会话产生的一些状态数据。
我们都知道,Http 协议本身是一个无状态协议,也就是服务器并不知道客户端发送过来的多次请求是属于同一个用户。
所以 Session 是用来弥补 Http 无状态的不足,简单来说,服务器端可以利用 session 来存储客户端在同一个会话里面的多次请求记录。
基于服务端的 session 存储机制,再结合客户端的 Cookie 机制,就可以实现有状态的 Http 协议。
(如图)具体的工作原理是:
客户端第一次访问服务端的时候,服务端会针对这次请求创建一个会话,并生成一个唯一的 sessionId来标注这个会话。
然后服务端把这个 sessionid 写入到客户端浏览器的 cookie 里面,用来实现客户端状态的保存。
在后续的请求里面,每次都会携带 sessionid,服务器端就可以根据这个 sessionid 来识别当前的会话状态。
在这里插入图片描述
所以,总的来看,Cookie 是客户端的存储机制,Session 是服务端的存储机制。这两者结合使用,来实现会话状态的存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值