回显服务器的代码:https://gitee.com/ql5435/java-servlet/tree/master/review/network/src/netword
TCP:有连接,可靠传输,面向字节流,全双工
UDP:无连接,不可靠传输,面向数据包,全双工
基于UDP的应用层协议:DHCP,DNS等
如何实现可靠传输:在应用层数据包里参考TCP的策略来实现
Socket 类,本质上相当于一个“文件”,在系统中,有一种特殊的 socket 文件,对应到网卡设备
构造一个DatagramSocket 对象,就相当于打开了一个内核中的 socket 文件,此时就可以通过 send receive 发送/接收文件了
表示一个 UDP 数据包
传输数据,就是以 DatagramPacket 为基本单位
IP 地址 + 端口号
accept方法
返回值是一个 Socket 对象,功能是等待有客户端和服务器建立上连接,accept 则会把这个连接获取到进程中,进一步的通过返回值的 Socket 对象来和客户端进行交互
通过 Socket 对象,就可以进行发送/接收数据了
这里的传输不是直接通过 Socket 对象完成的,而是 Socket 内部包含了 输入流InputStream,输出流OutputStrean对象
网络传输的机制:后发先置经常产生,所以两个人通信,在回复消息时,最好就指定针对哪条消息回复【QQ中就可以针对某条消息进行回复】,所以TCP引入了序号的机制,按照字节来编号
在确认应答的情况下,如果收到了ACK就好办,如果没收到,就需要超时重传
超时重传也不会无限制的重传下去,尝试几次后,若任然无法传输过去,就断开连接,尝试重连
在发送方无法感知是哪一个数据包丢,所以经过一段时间没有收到ACK应答,就会触发超时重传【接收方会根据序号来对数据去重–ACK丢包时,接收方就可能会收到多份一样的数据】
丢包操作,存在一个超时时间,这个时间在操作系统内核可以配置的;超时时间间隔会越来越大
三次握手,四次挥手
确认双方的接收能力与发送能力是否正常
除了验证双方通信能力外,还可以协商一些东西【如:序号机制从几开始】
FIN与ACK无法进行合并,FIN属于用户态操作,ACK属于内核态,中间间隔时间无法预估
提高传输效率的机制【还是不如无可靠性的 UDP的效率的】
本质上就是把等待ACK的时间重叠起来【减少等待时间,就相当于提高效率了】
一次发一批数据,然后等待一批ACK;在不等待的情况下,最多可以一次发送 N【窗口大小】条数据,N越大,发送的越快,但是太大了,也会操作网络拥堵
根据收到的ACK,来滑动窗口
还是会存在丢包问题,可是还是安全的吗?
用来控制滑动窗口的大小的【传输速率 = 发送速度【滑动窗口大小】 & 接收速度【应用程序 每次 read 的大小无法控制,但是可以用接收阻塞队列剩余空间来衡量接收速度】】,若滑动窗口的N太大了,可接收端接收不过来,就会网络拥堵,流量控制就可以控制滑动窗口 N 的大小【在应答报文的时候,会返回接收缓冲区剩余空间的大小】
如果接收缓冲区满了,那么发送方会短暂暂定发送,过一段时间会发送一个“探测报文”,来查看接收缓冲区此时的状态
流量控制的窗口大小是根据ACK报文来判断的
实验发送:刚开始按照小的窗口进行发送,如果不丢包就说明中间转发设备比较畅通,继续放大窗口;放大到一定程度,发生丢包后,会适应的减少窗口大小【使其动态平衡】 — 发送方通过实验找到拥塞控制的窗口大小的
在收到数据的时候,等一会在返回ACK,在这段时间中,可能接收方能接收更多的数据,那么接收缓冲区的剩余空间就会空出来多一点,发送方就可以根据这个窗口大小来增加发送速度了
滑动窗口【提高发送速度】,流量控制,拥塞控制【限制发送速度】,延时应答【提高发送速度】,来回博弈
前面说了ACK是内核态操作,收到数据后会立马返回ACK;但是现在有延时应答机制,ACK的返回会延迟一会,这时响应报文就可能遇到了ACK,那么就可能存在ACK和响应报文一起需要传回去,所以就有可能将两次传输合并到一个响应报文传回去了【也提高了传输速率】
主机关机
按照程序关机,会先杀死所有的用户进程(也就包括TCP程序)
杀死进程—> 释放进程PCB,释放文件描述符表上的文件资源(相当于调用close)
这个时候就会触发FIN,开启四次挥手操作
如果在挥手挥完了,继续关机(没啥特殊的);如果还没挥完,就关机了,对端重传FIN若干次,没有响应,也就放弃了
程序崩溃
同上,也是会正常四次挥手【虽然进程没了,但是TCP连接属于内核操作,内核会继续完成】,这就不存在挥手没挥完的情况
主机拔电源
来不及四次挥手【一个可以工作,另一个不能工作】
- 接收方掉电,发送方尝试发送数据,发现没有ack,尝试重传,重传几次,仍没有 ack,发送放尝试重连,如果重新连接也不成,认为是当前网络出现了问题,就放弃了
- 发送方掉电:接收方就在等待数据,由于发送方没了,显然数据到不了,接收方并不知道 是对方没发还是对方出问题了;接收方如果一段时间没有收到数据,就会定期给发送方发送一个“心跳包”【特殊报文,用来检查发送方状态】【心跳机制很重要,TCP里面有,应用程序有时候也会实现】
网线断开
和主机断电一样【两个都无法正常工作了】
只要是面向字节流的传输【文件读写】,都会涉及
看前面的图:面向字节流的数据包,TCP是无法区分每次传过来的数据包的,在TCP接收缓冲区内,不管收到几次数据包,都相当于一个数据
需要在应用层明确每次通过TCP传输过来的数据包