网络编程
对于这个网络编程的理解
首先呢网络编程就涉及到我们使用的计算机,在我们的因特网上进行数据交换和通信的编程活动。它不仅仅涉及一些本地文件以及 IO 处理,并且还涉及到在网络之间怎么去传输,他们内部是使用什么样的协议去进行数据的传输的。
# 网络通信协议
# 基础知识
通信指的是人与人之间进行信息传递的过程
网络网络的意思是一个抽象的概念,是点与点之间的连接组成的一个模型,就叫做网络。网络的出现,把我们各个点都连在了一起,让我们能够实现各个点之间的信息传递,从而达成各个点之间的信息资源共享。
协议就类似于一套语法。我们用中文的时候,有中文的语法,英文有英文语法、日文有日文语法,各种语言都有各种语言的语法。也就是说我们在交流的时候,说话一定要遵循一种语法,一种规范。类比一下,【协议】就叫做一种规范,也就是我们的通信设备在进行通信时需要遵守的一种规则就叫做协议。
网络通信涵盖了两个概念,就是我们在网络中使用一套规范进行信息的传递
网络通信协议:它主要是对信息传递的各种传递的速率、传递的代码、传递的数据结构以及传输的步骤、基层模型等等做出规定,并且制定出一套公认的标准。常用的网络通信协议有 tcp 和 IP 协议,这也就是我们在 web 中常用的一种通信协议。
TCP/IP 协议,互联网相关的协议集合起来统称为 TCP/IP
。
- transmission control protocol、 internet protocol 传输控制协议以及英特网协议
互联网也叫做国际网络或者叫因特网。互联网是一九六九年美国的阿 le 网网络和网络之间所串成的一个庞大的网络。这些巨大的网络之间,都是以一种通用的协议相连的形成。一个巨大的国际网络使用互互联网就可以把我们的信息瞬间发送到千里之外的人手中。它是信息社会的基础,因特网上的计算机使用的就是 tcp/ip 协议
计算机网络是通信技术和计算机技术相结合的一个产物。计算机网络是按照网络协议,把地球上分散独立的计算机相互连接的一个集合。连接介质可以是电缆、双绞线、光纤、微波载波或通信卫星。计算机网络具有共享硬件、软件、数据资源的功能,具有对共享数据资源集中处理以及管理和维护的能力。
计算机网络常常被分为局域网、城域网和广域网。中国的就是一个巨大的局域网
TCP
中的七层模型
# TCP和UDP
TCP(Transmission Control Protocol)是面向连接的通信协议,在传输数据之前会在发送端和接收端之间建立一个逻辑连接,然后再传输数据。
它提供了两台计算机之间稳定的数据传输,通过建立三次握手就可以进行数据传输。在关闭连接时,需要进行四次挥手操作。
TCP协议可以保证传输数据的安全性,因此被广泛应用,用于下载文件、浏览网页等常见场景。
UDP(User Datagram Protocol)是一个面向无连接的协议,传输数据时无需建立连接。不管对方的服务是否启动,数据会直接封装并发送到目的地。每个包的大小在64KB以内。它不是一个可靠的协议,因为没有连接,所以传输数据很快,但容易丢失数据。在视频会议直播等场景中通常会采用UDP。
# 三次握手四次挥手
三次握手是为了保证双方连接的正确性
在Google Groups的TopLanguage中看到一帖讨论TCP“三次握手”觉得很有意思。贴主提出“TCP建立连接为什么是三次握手?”的问题,在众多回复中,有一条回复写道:“这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.”。
三次握手的过程个人理解
首先,第一次握手是 client 端,向 server 端发送一个 SYN。此时我们的 server 端可以确定 client 端的发送是正常的,并且本身的接收也是正常的。那么在这个时候,server 端开启第二次握手,向 client 端发送了一个 SYN 连同 ACK 的信息。此时 client 接收到 server 的信息。那么这个时候可以确认 server 端能够接收并且能够发送信息。但是此时 server 端并不能确认 client 端是否有接收信息的能力。因此在这个时候,client 端再向 server 端发送一个 ACK 的信息,让 server 端确认 client 端能够接收到信息。这样三次握手就完成了。
四次挥手过程:
首先,第一次是 client 还是 server,发出的都是可以的
在TCP连接中,四次挥手的过程如下:
- 客户端发送一个终止连接的请求给服务器端。这个请求包含一个设置了FIN标志的TCP报文段。这表示客户端不再有数据要发送给服务器端了,但是仍然可以接收数据。
- 服务器端接收到这个FIN后,会发送一个ACK确认收到,表明它也准备好关闭连接。此时,服务器端不会立即关闭连接,而是等待已经发送的数据都被接收,即等待读取操作结束。
- 服务器端在完成数据的发送后,会发送一个FIN给客户端,表示服务器端已经完成发送,并且准备关闭连接。
- 客户端收到服务器端的FIN后,会发送一个ACK确认收到。此时,客户端在发送完这个ACK后会等待一段时间,以确保服务器端接收到这个确认。一旦确认被接收,客户端和服务器端的连接就关闭了。
# URI
- URI(Uniform Resource Identifier)是用来标识某一资源的字符串的简洁表示。它可以是 URL 或 URN,只要能够唯一地标识资源即可。
- URL(Uniform Resource Locator)是一种特定类型的URI,它提供了标识某一资源的手段,其中包括了该资源的位置以及访问的方式。通常,URL将指向资源的具体位置,例如网页、图片或其他在线内容。
- URN(Uniform Resource Name)也是 URI 的一种特定形式,它的作用是通过名称来独一无二地标识资源。URN的设计初衷是为了提供一种持久且独一无二的资源标识符,不受资源位置、访问方式变化的影响。
一个 url 包含了什么?
# HTTP与HTTPS
- HTTP的URL由“http:/"起始且默认使用端口80,而HTTPS的URL由“https://"起始且默认使用端口443。
- http 安全性没有 https 高,但是 https 比 http 要消耗更多的服务器资源
对称加密密钥只有一个。加密解密都是同一个密码,而且加解密速度快,典型的对称加密算法有 DES、AES 等等
非对称加密密钥成对的出现,并且根据公钥 public key 无法推知私钥。根据私钥,也没有办法推知公钥加密解密使用不同的密钥。公钥加密需要私钥解密。私钥加密需要公钥解密相对对称的加密速度比较慢,典型的非对称加密算法有RSA、DSA 等
除此之外,随着技术的不断发展以及量子计算机的应用,RSA安全性将再次遭遇挑战。谷歌CEO Sundar Pichai曾预言,
“5-10年间,量子计算将会打破我们如今所知道的加密技术”。
# BIO与NIO
- 【动画讲解:BIO有哪些不足,为什么会产生NIO和select、poll、epoll多路复用技术】 https://www.bilibili.com/video/BV1qX4y1H7gm/?share_source=copy_web&vd_source=247958e5546dd3e7e1f29c2624cdfdca
# IO 模型简介
# 历史
首先,我们说到 BIO 和 NIO,我们就得说一下关于 IO 的历史
BIO
:低性能,同步,阻塞- 是一个比较传统的 IO 模型,它通常在 GDP1.4以前被广泛使用。
- 也就是零二年以前,我们使用的
IO模型
都是基于 bio 的。它的一个特点是阻塞性。也就是说:它必须等待上一个 IO 操作完成之后才能进行下一步的操作。 - 它是一个面向流的处理器,每次处理一个字节的数据,因此整体的速度相对来说是很慢的
NIO
:高性能,同步,非阻塞- 是在 jdk1.4中引入的一种新的 IO 模型。它的一个特点是高性能同步、非阻塞。相比较于 bio,nio 是基于缓冲区进行数据读写的,也就是以块(buffer)的方式对数据进行处理,处理的速度要比按逐个逐个的按字节来处理要快很多。这种方式是很多主流的处理库的一个实现方式。例如说netty、tomcat
- 高性能
- 缓冲区(Buffer):NIO 使用缓冲区来进行数据的读写操作,通过直接或间接的方式管理数据。相较于 BIO 来说,单次处理的数据量变大,同样一份数据复制的次数变少了,提高了 IO 操作的效率
- 通道(Channel):NIO 中的通道是双向的,可以同时支持读和写操作。通道的引入使得数据可以直接从通道读取到缓冲区中,或者直接从缓冲区写入到通道中,减少了数据在内存和IO设备之间的来回拷贝。
- 选择器(Selector):通过一个单线程的 selector,去对我们的多个连接进行统一的管控,相较于上一代BIO一个线程只能处理一个连接,大大提升了效率。(大大减少了线程的浪费)。NIO 通过选择器实现了多路复用机制,允许单个线程同时监控多个通道的IO事件。这使得单个线程能够有效地管理和处理多个连接,高效地复用了资源,减少了线程数目和上下文切换的开销。
AIO
是一种高性能的异步非阻塞的 IO 方式,它是在 jdk1.7里面引入的,可以看作是 nio 的升级版。aio 基于视线和回调机制,使得我们的 IO 操作不是同步,而是异步的。这种模型很好的利用了系统资源,提高系统的并发能力和响应速度AIO
它有点类似于我们并发编程里面的 future task 的特性。它可以将我们的任务指向另外一个线程,让另外一个线程帮我们完成,就等于它是集成了一个多线程的操作。可以帮助我们提高并发能力。- 在AIO模型中,可以将I/O操作交给另一个线程处理,这样当前线程不需要阻塞等待I/O操作的完成,从而提高了并发能力。AIO利用了操作系统底层提供的异步I/O机制,使得应用程序可以在发起I/O操作后执行其他任务,而无需等待I/O操作的完成。这种异步I/O模型对于高并发、高吞吐量的场景非常有用。
五种 IO 模型:https://www.51cto.com/article/747462.html
# BIO
在jdk1.4以前,我们建立网络连接只能采用BIO。我们首先需要在服务端去启动一个ServerSocket,然后在客户端启动一个Socket来对服务端进行通信。
- 默认情况下,服务端需要对每个请求建立一个线程等待请求。而客户端发送请求之后,先会咨询服务端是否有线程响应。这里用到了一个TCP的协议,如果没有,就会一直等待或者遭到拒绝。如果有线程可以响应的话,客户端的线程会等待这个请求,结束之后才会继续执行,这就是阻塞式的IO。
- 服务端需要为每个连接创建一个独立的线程来处理请求,而客户端在发送请求后会等待服务端的响应,如果没有响应就会一直等待或遭到拒绝。这种模式下,I/O 操作是阻塞的,也就是说当一个 I/O 操作在执行时会阻塞当前线程,直到操作完成或超时。
# NIO
缓冲区 buffer 实际上是一个容器,它是一个特殊的数组。缓冲区对象内置的一些机制,可以跟踪和记录缓冲区里面的状态变化情况
NIO 中的通道(Channel)是双向的, 既可以用来进行读操作,也可以用来进行写操作。提供从文件或者是网络读取数据的一个通道,但是读取或者写入的数据都必须经过 buffer
# 复制文件
// BIO复制文件:不好理解,而且代码很冗余
public static void testBioCopy() throws IOException {
try (FileInputStream fileInputStream = new FileInputStream("nioFile.txt"); FileOutputStream fileOutputStream = new FileOutputStream("bioFile.txt")) {
/*冗余代码开始了*/
byte[] bytes = new byte[1024];
while (true) {
int read = fileInputStream.read(bytes);
if (read == -1) {
break;
}
fileOutputStream.write(bytes, 0, read);
}
}
}
// 测试 nio 的复制方法.可以看到,这种方法比 bio 要先进一点
public static void testNioCopy() {
try (FileInputStream fileInputStream = new FileInputStream("nioFile.txt"); FileOutputStream fileOutputStream = new FileOutputStream("bioFile.txt")) {
FileChannel oc = fileOutputStream.getChannel();
FileChannel ic = fileInputStream.getChannel();
oc.transferFrom(ic, 0, ic.size());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 做一个小 demo
一个简单的网络聊天室,里面的一个要点就是当我们的请求发送到 selector 的时候,我们对 selector 的信息进行处理时,我们需要将这个消息重新广播到其他的 channel 中。这样就完成了一个消息的发送
需要注意,第一件事是每次完成了一个 channel 的事件处理之后,我们需要手动的 remove 掉这个 selection key,否则的话下次他还会重复处理
# 对比总结
BIO主要适用于连接数目较小而且稳定的架构,它是一种同步阻塞。举个例子,就是去食堂排队取餐,我们端着盘子,只能等前面的人拿完东西。取完餐之后,我们才能够处理完我们的取餐请求,然后我们才能找位置吃饭,完成我们的吃饭操作。这就是一个需要阻塞、等待的一种IO方式。
而NIO的方式呢,它适用于连接数目较多,并且连接比较短。也就是我们的文件没那么多的一个架构。比如说聊天服务器,它是从JDK 1.4开始支持的,它是一种同步非阻塞的IO方式。就例如我们下馆子,我们点完餐之后,我们可以去商场里面玩一会儿,然后玩完了之后再回来,然后只要回来问一下餐馆,好了没好了就可以开始处理了。但是这里的话我们可能会不断地轮询,不断地去问他有没有这样的时间。然后问完了之后,我们还是继续下面的一些处理我们请求的一些操作。
AIO适用于连接数目多,并且连接比较长,是重操作的一种架构。比如说我们的相册服务器,它要充分地调用操作系统参与并发操作。编程是比较复杂的,它是从JDK 7开始支持异步非阻塞。比如说我们海底海底捞的一个外卖火锅,我们可以打电话订餐。然后海底海底捞会说,我知道你的位置,我一会给你送过来,请你安心的工作,这也是一种最好的方式。但是他的操作非常复杂。