目录
一.UDP协议
要了解UDP协议,就先理解协议的报文格式.拼装报头的过程,就是所谓的""封装"".
UDP长度:即整个UDP数据报的长度(报头+载荷),该长度是使用两个字节的 长度来表示的,两个字节能表示的数据范围为0~65535,即一个数据报最大就是64kb,不能超过这个大小,一旦超过可能就会造成数据丢失,后果比较严重.
如何避免一个数据报的大小超过64kb呢?
两个方案: 1.在应用层代码中,对广告数据进行切分,分成多个UDP数据报,返回给上游的服务器,虽然可行,但是太麻烦了.因为在应用层进行拆分根合并是不容易实现的,并且很容易引出一些bug. 并且可能会存在:后发先至"的情况",假设发生数据为1,2,3三个数据,但在接受端收到的数据可能是1,2,3,也可能是3,2,1这个顺序,这就造成了很大的麻烦.这中方法不推荐 2.直接改成TCP来实现 TCP在网络传输对数据的长度是没有限制的.
UDP校验和
在网络上传输数据,是可能会出现一些问题的.网络上传输的数据本质是一些0/1bit流,这些bit流通过光信号或者电信号来表示的. 如果传输过程 收到一些干扰,就 容易出现“比特翻转”的情况(0->1,1->0),而校验和就是为了验证当前的数据是否出现了问题
校验和是会变的,例如:买了一种菜的时候校验和是1,两中菜校验和就是2.与校验和一样不一定是正确的,但是与校验和不一样就一定不正确.
校验和往往是通过原始数据 的 内容生成的,不同的内容生成的校验和就不一样.一旦数据发生变化,校验和就不一样.就可以通过校验和来判断当前的数据是否发生了变化.
实现校验和的算法有很多,常见的有:crc,md5.
二.TCP协议
TCP协议段格式
有关TCP的特性: 1.有连接 2.可靠传输 3.面向字节流 4.全双工
2.1保证可靠的核心
2.1.1确认应答
发送方发送数据给接受方了,接收方回应一个应答报文.如果发送方收到了这个应答报文就说明接收方收到了数据的.
由于网络上的传输,接受到的顺序是不确定的,因此不能就单纯的按照通过收到的顺序来确定逻辑.因此此处引入了序号和确认序号,即在协议格式中出现的序号和确认序号.
那么此时即使接受到的顺序,有着序号和确认序号就不会混乱了.
因为实际上,TCP传输数据是不论条的,是论字节的(面向字节流),因此序号和确认序号就是以字节为单位进行编号的.
编号是针对每个字节进行编号,依次进行累加.而且实际上序号的起始不一定是从1开始的.假设第一个请求,A给B发生了1000个字节的数据,序号就是1-1000,长度为1000,因此确认应答数据报的确认序号就是1001.意思就是,1001之前的数据,B已经收到了,另外,也可以理解成B在向A索要1001开始的数据。
发生方就可以根据确认的应答报文来确定接受方是否收到。只要发送方收到了应答,就认为接受方收到了,可靠传输就完成了。
2.1.2 超时重传
不可否认,确认应答机制是在数据传输比较顺利的情况来实现的。但在传输的过程 中可能会出现丢包。一旦数据丢包,就要进入超时重传的机制中了。
这两种情况,发送方无法区分,当前的发的数据丢了,还是应答数据丢了。发送方没有收到应答报文,那么能做到的事情就只能过段时间后重新发送信息。
要过段时间再发送的原因: 数据在 网络上传输是需要时间的,不是说这个数据刚发出去,就期望得到回应。可能要经过一段时间才能收到回应,但当没有收到应答报文,就会过段时间重新发送,具体多长时间,不同的系统实现方式不一样。
2.1.3 连接管理
连接管理说的就是,如何建立连接(三次握手),如何断开连接(四次握手)。这两个都是TCP中最高频的问题。是在内核上进行的。
三次握手:
本质上,就是A向B请求连接,B给予回应,B也向A请求连接,A也给予回应。这是四个步骤。但是B给予回应和B也向A请求连接可以合并为一个操作。
如果三次操作改为四次握手也不是不可以,只不过还要多设置一个数据报类型并且传输,因为服务器发送SYN和ACK都是在同一个时机,由操作系统内核完成。我们都知道网络传输这些数据报要涉及到封装和分用的,每一个数据报的封装和分用的步骤也是非常多的。而三次握手改为两次握手是不行的。
三次握手的目的: 1.投石问路:通过三次握手的过程,来确认A和B之间的传输是通畅的。尤其是要确认,A和B之间的各自的发送能力以及接受能力是否正常。
如果网络出现问题,此时三次握手都会难以成功,此时就没有必要进行后续的传输了。
2.协商参数:通过三次握手,让A和B之间协商,选择一些传输中合适的参数,如TCP的序号从几开始。
服务器两种关键的状态: 1.LISTEN:说明服务器已经启动,随时可以连接.当创建好了ServerSocket实例后,就进入了listen 2.ESTABLISHED:说明服务器和客户端的接受和发送都没有问题,已经可以开始通信了,等同于代码中accept方法返回,得到一个clientSocket实例.
四次挥手:A是客户端,B是服务器
此处ACK和FIN不是同时发送的原因: ACK和FIN发送的时机是不一样的,ACK是由内核来完成发送的,服务器发送的FIN是由代码决定的.它是当服务器一收到客户端发送FIN后,就会立刻发送ACK了,而服务器发送FIN的时机有两种情况: 1.当代码中调用了client.close()方法,服务器才会发送FIN