UDP与TCP

UDP与TCP

回显服务器的代码:https://gitee.com/ql5435/java-servlet/tree/master/review/network/src/netword

两者区别

TCP:有连接,可靠传输,面向字节流,全双工

UDP:无连接,不可靠传输,面向数据包,全双工

面向字节流与面向数据包

UDP与TCP_第1张图片

UDP

基于UDP的应用层协议:DHCP,DNS等

如何实现可靠传输:在应用层数据包里参考TCP的策略来实现

Socket API

DatagramSocket

Socket 类,本质上相当于一个“文件”,在系统中,有一种特殊的 socket 文件,对应到网卡设备

构造一个DatagramSocket 对象,就相当于打开了一个内核中的 socket 文件,此时就可以通过 send receive 发送/接收文件了

DatagramPacket

表示一个 UDP 数据包

传输数据,就是以 DatagramPacket 为基本单位

InetSocketAddress

IP 地址 + 端口号

UDP 版本的 echo 服务器

UDP与TCP_第2张图片

报文格式

UDP与TCP_第3张图片

TCP

Socket API

ServerSocket

accept方法

返回值是一个 Socket 对象,功能是等待有客户端和服务器建立上连接,accept 则会把这个连接获取到进程中,进一步的通过返回值的 Socket 对象来和客户端进行交互

Socket

通过 Socket 对象,就可以进行发送/接收数据了

这里的传输不是直接通过 Socket 对象完成的,而是 Socket 内部包含了 输入流InputStream,输出流OutputStrean对象

TCP协议报头格式

UDP与TCP_第4张图片

为了保证可靠传输的机制

确认应答

网络传输的机制:后发先置经常产生,所以两个人通信,在回复消息时,最好就指定针对哪条消息回复【QQ中就可以针对某条消息进行回复】,所以TCP引入了序号的机制,按照字节来编号

序号机制

UDP与TCP_第5张图片

超时重传

在确认应答的情况下,如果收到了ACK就好办,如果没收到,就需要超时重传

超时重传也不会无限制的重传下去,尝试几次后,若任然无法传输过去,就断开连接,尝试重连

普通报文丢包 与 ACK丢包

在发送方无法感知是哪一个数据包丢,所以经过一段时间没有收到ACK应答,就会触发超时重传【接收方会根据序号来对数据去重–ACK丢包时,接收方就可能会收到多份一样的数据】

丢包操作,存在一个超时时间,这个时间在操作系统内核可以配置的;超时时间间隔会越来越大

连接管理

三次握手,四次挥手

三次握手

确认双方的接收能力与发送能力是否正常

除了验证双方通信能力外,还可以协商一些东西【如:序号机制从几开始】

UDP与TCP_第6张图片

四次挥手

FIN与ACK无法进行合并,FIN属于用户态操作,ACK属于内核态,中间间隔时间无法预估

UDP与TCP_第7张图片

状态

UDP与TCP_第8张图片

滑动窗口

提高传输效率的机制【还是不如无可靠性的 UDP的效率的】

本质上就是把等待ACK的时间重叠起来【减少等待时间,就相当于提高效率了】

一次发一批数据,然后等待一批ACK;在不等待的情况下,最多可以一次发送 N【窗口大小】条数据,N越大,发送的越快,但是太大了,也会操作网络拥堵

根据收到的ACK,来滑动窗口

UDP与TCP_第9张图片

是否可靠?

还是会存在丢包问题,可是还是安全的吗?

  1. 若前面 ACK 丢了,但是后面的 ACK 会覆盖前面的情况【若1001确认报文丢失,可2001到达了,那么就表示1-2000都已收到,下一次发送从2001开始】,若是最后一个ACK丢包,就会超时重传了
  2. 普通报文丢了:应答报文会重复发送未接收到的报文序号【在这中间传输的数据,不用再重新传一遍】

UDP与TCP_第10张图片

流量控制

用来控制滑动窗口的大小的【传输速率 = 发送速度【滑动窗口大小】 & 接收速度【应用程序 每次 read 的大小无法控制,但是可以用接收阻塞队列剩余空间来衡量接收速度】】,若滑动窗口的N太大了,可接收端接收不过来,就会网络拥堵,流量控制就可以控制滑动窗口 N 的大小【在应答报文的时候,会返回接收缓冲区剩余空间的大小】

如果接收缓冲区满了,那么发送方会短暂暂定发送,过一段时间会发送一个“探测报文”,来查看接收缓冲区此时的状态

流量控制的窗口大小是根据ACK报文来判断的

拥塞控制

实验发送:刚开始按照小的窗口进行发送,如果不丢包就说明中间转发设备比较畅通,继续放大窗口;放大到一定程度,发生丢包后,会适应的减少窗口大小【使其动态平衡】 — 发送方通过实验找到拥塞控制的窗口大小的

窗口大小变化

UDP与TCP_第11张图片

延时应答

在收到数据的时候,等一会在返回ACK,在这段时间中,可能接收方能接收更多的数据,那么接收缓冲区的剩余空间就会空出来多一点,发送方就可以根据这个窗口大小来增加发送速度了

滑动窗口【提高发送速度】,流量控制,拥塞控制【限制发送速度】,延时应答【提高发送速度】,来回博弈

捎带应答

前面说了ACK是内核态操作,收到数据后会立马返回ACK;但是现在有延时应答机制,ACK的返回会延迟一会,这时响应报文就可能遇到了ACK,那么就可能存在ACK和响应报文一起需要传回去,所以就有可能将两次传输合并到一个响应报文传回去了【也提高了传输速率】

Tcp连接出现异常,如何处理

主机关机

按照程序关机,会先杀死所有的用户进程(也就包括TCP程序)

杀死进程—> 释放进程PCB,释放文件描述符表上的文件资源(相当于调用close)

这个时候就会触发FIN,开启四次挥手操作

如果在挥手挥完了,继续关机(没啥特殊的);如果还没挥完,就关机了,对端重传FIN若干次,没有响应,也就放弃了

程序崩溃

同上,也是会正常四次挥手【虽然进程没了,但是TCP连接属于内核操作,内核会继续完成】,这就不存在挥手没挥完的情况

主机拔电源

来不及四次挥手【一个可以工作,另一个不能工作】

  1. 接收方掉电,发送方尝试发送数据,发现没有ack,尝试重传,重传几次,仍没有 ack,发送放尝试重连,如果重新连接也不成,认为是当前网络出现了问题,就放弃了
  2. 发送方掉电:接收方就在等待数据,由于发送方没了,显然数据到不了,接收方并不知道 是对方没发还是对方出问题了;接收方如果一段时间没有收到数据,就会定期给发送方发送一个“心跳包”【特殊报文,用来检查发送方状态】【心跳机制很重要,TCP里面有,应用程序有时候也会实现】

网线断开

和主机断电一样【两个都无法正常工作了】

粘包问题

只要是面向字节流的传输【文件读写】,都会涉及

看前面的图:面向字节流的数据包,TCP是无法区分每次传过来的数据包的,在TCP接收缓冲区内,不管收到几次数据包,都相当于一个数据

解决粘包问题

需要在应用层明确每次通过TCP传输过来的数据包

  1. 使用分隔符
  2. 约定长度

你可能感兴趣的:(tcp/ip,udp,网络)