温故而知新
目录
网络分层
一. 应用层
应用程序
现成的应用层协议有超文本协议http(不仅仅有文本).
http协议
http://t.csdnimg.cn/e0e8khttp://t.csdnimg.cn/e0e8k
自定义应用层协议,包含需要传输的信息以及格式,将信息转为字符串放入TCP或者UDP的socket中。常见传输格式xml,最流行的是json,但json仍然有网络带宽的消耗,protobuffer是将信息压缩为二进制,带宽消耗较小。
二. 传输层
1. 介绍
关注起点和终点
主要有TCP和UDP :
TCP:有连接,可靠传输,面向字节流,全双工。适用于需要确保数据完整性和顺序的场景。eg:文件传输,状态更新。
UDP:无连接,不可靠传输,面向数据报,全双工,接收缓冲区。适用于高速传输和对实时性要求较高的应用。
传输层一个重要概念:端口号
固定占2个字节,
表示范围0~65535(2^16-1),
0一般不用,1~1023是知名端口号,如80是http的端口号22是ssh的端口号(登录远程主机)
2.UDP协议
(1)组成
UDP的首部长度固定为8个字节(64位)64k。它由源端口号、目标端口号、长度和校验和组成。每个字段都占用2个字节。
- 源端口号(Source Port):占用2个字节,表示发送方使用的端口号。
- 目标端口号(Destination Port):占用2个字节,表示接收方使用的端口号。
- 长度(Length):占用2个字节,表示UDP首部和数据的总长度,包括8字节的UDP首部和数据部分的长度。
- 校验和(Checksum):占用2个字节,用于检测UDP首部和数据在传输过程中是否发生错误。
UDP的简洁首部长度是其相对于TCP更轻量级的一个特点,但也意味着它没有TCP那样的可靠性保证和流量控制机制。因此,在使用UDP时需要注意数据的可靠性和完整性问题,并根据具体应用场景决定是否需要额外的机制来处理这些问题。
(2)细节
✅1.当udp数据报携带信息过大,导致服务器与客户端交互的数据量接近64kb,超过上限会导致数据阶段,数据出错,解决办法:
1.将数据拆分为多个包,使用多个UDP传输(✕)如何去拆包组包,开发测试成本大。
2.使用TCP,无包大小的限制(✓)
3.升级UDP,比较麻烦。(✕)UDP是在操作系统内核实现的.
✅2.网络传输中数据是有可能出错的,如何基于校验和来完成数据校验呢?
1.发送方,把要发送的数据整理好(称为 data1),通过一定的算法, 计算出校验和 checksum1发送方把 data1 和 checksum1 -起通过网络发送出去.
2.接收方收到数据,收到的数据称为 data2 (数据可能和 data1 就不一样了),收到数据 checksum1
3.接收方再根据 data2 重新计算校验和(按照相同的算法),得到 checksum2
4.对比 checksum1 和 checksum2 是否相同.如果不同,则认为 data2 和 data1 一定不相同如 5.checksum1 和 checksum2 相, 则认为 data1 和 data2 大概率是相同的 理论上存在不同的可能性。
**✅3.在UDP中使用循环冗余校验(CRC):**把需要进行校验和的数据的每个字节逐个累加,把结果保存在两个字节的变量中,累加过程溢出也没事。如果中间出现数据错误,第二次的校验和就和第一次不也一样。
更严谨的是md5,MD5进行了定长,分散(一个字节不同差异也很大),不可逆。MD5也适合作为hash算法(哈希表是把一个key通过hash函数转换为数组下标,hash函数尽量分散,哈希碰撞的可能从才能降低),
✅4.UDP特点:寄信
UDP进行网络通信可以通过
java.net
包下的DatagramSocket
和DatagramPacket
类来实现无连接:知道对方ip和端口号即可连接,
不可靠 :发送端发送数据报后,如果因为网络问题并没有到接收方,UDP协议也不会给应用层返回任何错误信息。
全双工:可以通过一个socket进行send和reseive,既能读也能写,即全双工;
**缓冲区:**UDP只有接收缓冲区,没有发送缓冲区。
UDP发送的数据会直接发送给内核,由内核将数据传给网络层协议进行后续传输动作;UDP具有接收缓冲区,这个缓冲区不能保证受到道德UDP报的顺序与发送UDP报的顺序一致;缓冲区满,再到达的UDP报就会被 丢弃。
大小受限:UDP协议首部有一个16位的最大长度,2个字节,也就是UDP能传输的最大长度是64KB(包含UDP首部)
面向数据报:以DataGaramSocket为单位传输
javaDatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, receiverAddress, receiverPort);
UDP是一种面向数据报的无连接协议,因此发送方和接收方之间不存在建立连接的过程,也没有可靠性保证。每个UDP数据报都是独立的,可能会丢失、重复或乱序。实际使用中可能需要考虑超时重传,分片传。
javaimport java.net.DatagramSocket; import java.net.DatagramPacket; import java.net.InetAddress; public class UDPExample { public static void main(String[] args) { try { // 创建发送方的UDP socket DatagramSocket senderSocket = new DatagramSocket(); // 准备要发送的数据 String message = "Hello, UDP!"; byte[] sendData = message.getBytes(); InetAddress receiverAddress = InetAddress.getByName("127.0.0.1"); // 接收方的IP地址 int receiverPort = 12345; // 接收方的端口号 // 创建要发送的数据报文 DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, receiverAddress, receiverPort); // 发送数据报文 senderSocket.send(sendPacket); // 创建接收方的UDP socket DatagramSocket receiverSocket = new DatagramSocket(receiverPort); // 准备接收数据的缓冲区 byte[] receiveData = new byte[1024]; // 创建接收数据的数据报文 DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); // 接收数据报文 receiverSocket.receive(receivePacket); // 解析接收到的数据 String receivedMessage = new String(receivePacket.getData()); System.out.println("Received message: " + receivedMessage); // 关闭socket senderSocket.close(); receiverSocket.close(); } catch (Exception e) { e.printStackTrace(); } } }
5.UDP无连接不可靠面向数据报的协议如果要基于传输层UDP协议来实现可靠传输应该如何设计?大小有限制,如果要基于传输层UDP协议,传输超过64k的数据,如何设计?
参考TCP可靠性的实现
5.2+5.1分片重组+序列化保证顺序;5.1确认应答;超时重传;滑动窗口控制流量,校验和.......
简单了解基于UDP的应用层协议
NFS: 网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议 (用于无盘设备启动)
·DNS: 域名解析协议
3.TCP协议
(1)特性如下链接:
(2)组成
初心:可靠传输~
数据报=首部(报头)+载荷;一行4个字节
报头长度是不固定的,选项也是报头的一部分,TCP报头包括固定部分和可选部分。固定部分的长度是20个字节(160位),包括源端口号、目标端口号、序列号、确认号、数据偏移、控制位、窗口大小、校验和和紧急指针等字
报头最短是20个字节(没有选项),最长是60个字节(选项最多是40字节);
保留位(6位):有需要就用。比udp的64kb好。扩展余地。
TCP首部长度字段占用4个位(即4个二进制位也就是4个字节,32个比特位),它使用4位来表示长度。由于4位最多能表示16个不同的取值(从0000到1111),因此TCP首部长度字段的取值范围是0-15,表示TCP首部的长度是以32位(此处设定4字节,所以有4倍的设定关系)为单位的倍数。也就是说,长度值乘以4才得到TCP首部的实际长度。当TCP首部长度字段取值为5时,长度为5 * 4 = 20字节,即TCP首部固定部分的长度。
TCP协议的组成主要包括以下部分:
- 源端口号(Source Port):占用2个字节,表示发送方使用的端口号。
- 目标端口号(Destination Port):占用2个字节,表示接收方使用的端口号。
- 序列号(Sequence Number):占用4个字节,表示本次传输的第一个字节的序列号。
- 确认号(Acknowledgment Number):占用4个字节,表示期望接收到的下一个字节的序列号。
- 数据偏移(Data Offset):占用4个位,表示TCP首部长度,单位为4字节,因此TCP首部长度最大值为60字节。
- 保留位(Reserved):占用6个位,保留未来使用,必须设置为0。
- 控制位(Flags):占用6个位,包含ACK、SYN、FIN等标志位,用于控制TCP连接的建立、维护和关闭。其中ack为1,表示它表示应答报文,ack为0表示普通报文。SYN为。
- 窗口大小(Window Size):占用2个字节,表示接收窗口的缓冲区大小,用于流量控制。
- 检验和(Checksum):占用2个字节,用于检测TCP首部和数据在传输过程中是否发生错误。
- 紧急指针(Urgent Pointer):占用2个字节,表示紧急数据的位置,用于处理紧急数据。
(3)特点
有连接
javaSocket clientSocket = serverSocket.accept(); accept方法会阻塞当前线程直到有客户端连接请求到达并被接受 记得抛出异常防止网络故障类问题
可靠传输+面向字节流+全双工(既可以读也可以写)
java// 获取输入输出流 BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
💡TCP的可靠不在于它是否可以把数据100%传输过去,而是
- 1.发送方发去数据后,可以知道接收方是否收到数据;
- 2.如果接收方没收到,可以有补救手段;
三. 网络层
关注路径规划
四. 数据链路层
关注路径中节点的连接
五. 物理层
关注设备