努力经营当下 直至未来明朗!
1)分层最大的好处,类似于面向接口编程:定义好两层间的接口规范,让双方遵循这个规范来对接。
2)在代码中,类似于定义好一个接口,一方为接口的实现类(提供方,提供服务),一方为接口的使用类(使用方,使用服务):
对于使用方来说,并不关心提供方是如何实现的,只需要使用接口即可
对于提供方来说,利用封装的特性,隐藏了实现的细节,只需要开放接口即可。
3)这样能更好的扩展和维护。
有连接
可靠传输
面向字节流
有接收缓冲区,也有发送缓冲区
大小不限
③ 对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收
无连接
不可靠传输
面向数据报
有接收缓冲区,无发送缓冲区
大小受限:一次最多传输64k
③ 对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节;而不能分100次,每次接收1个字节。
① 有无连接:如打电话是有连接的,发微信是没连接的。即有连接是要先建立连接后才可以通信,无连接是可以直接进行发送。
② 可靠传输:不是说A给B发的数据100%能够让B收到,而是A可以知道B有没有收到。
③ 字节流:IO的章节有介绍,如InputStream、OutputStream,即TCP是基于流的。
④ 面向数据报:UDP是以“数据报”为基本单位的
⑤ 全双工相对的词是半双工。
全双工:一个通道,双向通信; 半双工:一个通道,单向通信。
网络通信一般都是全双工。
【可靠传输:指的是数据传输过去之后,发送方能够知道自己是发送成功还是没成】
例如,第一次出现丢包时,发送方就会在达到超时时间阈值之后进行重传;如果重传的数据仍然无响应,那么还会继续进行超时重传,但是第二次超时时间一般要比第一次更长,也就是超时时间并不是均等的,而是逐渐变大的。
【超时时间逐渐变大的理由】:如果单个数据报丢包的概率较小,此时由概率论计算可知第二次传输大概率是可以顺利到达的;如果第二次传输也没有到达的话,一般就说明当前环境比较糟糕,此时单个数据报丢包的概率就非常大了,如此就算传输再频繁也是无济于事的,倒不如降低传输频率以节省主机开销。
3)这样的重传如果在重试几次之后依旧无法传输,就会尝试重置TCP连接(也就是:断开重连);此时如果还是连不上就直接释放连接(彻底放弃连接)。
① 投石问路:检查一下当前的网络状况是否畅通。(三次握手建立连接其实并不传输任何业务信息)
② 三次握手同时也是在检查通信双方的发送能力和接收能力(两次是不行的,测试不完整)
③ 三次握手过程中,也在协商一些重要的参数。如TCP序号并不是从1开始的,通常是在建立连接的时候协商的数字,如果连接断开又快速重连,接收方就可以区分当前收到的数据是上个连接还是当前连接。
3)【两个重点的TCP状态:(建立连接)】
① LISTEN:服务器启动且绑定端口之后(new ServerSccket完成),相当于手机开机、信号良好,别人可以进行打电话。
② ESTABLISHED:连接建立好之后的稳定状态,相当于拨通电话之后可以进行说话交流了。
4)断开连接:四次挥手
5)为什么“三次握手四次挥手”?
① 在“三次握手”中,主机B给主机A返回确认ACK以及申请连接SYN都是由内核触发的,时机完全相同,操作系统就会把两个包合并成一个
(为啥不能是“四次握手”:可以但没必要,白白浪费时间)
② 在“四次挥手”中,ACK和FIN的触发时机是不相同的,ACK是由操作系统内核收到主机A给B发送的FIN之后立即触发的,而主机B给A发送FIN是应用程序显式的调用socket的close方法触发的。
6)两个重要的TCP状态(断开连接):
① CLOSE_WAIT:等待代码中调用close操作。(如果服务器上出现大量的CLOSE_WAIT状态的连接,说明服务器代码bug,close没有被及时调用到)
② TIME_WAIT:返回ACK的一方会进入TIME_WAIT。
如:主机A在处理完上一个ACK之后不能立即释放连接,而是需要保持一定时间,这是为了万一最后的ACK丢了,还有机会进行重传。(也就是说:如果A给B发送确认ACK的时候ACK丢包了,那么此时B就需要给A重新发送FIN,此时A处的TIME_WAIT就是非常必要的,如果A在等了一段时间之后没有FIN重传过来就认为ACK顺利到达了)
【指数增长可以在短时间内摸清楚网络承载的底线,而为了防止翻倍太快一下超过上限就设置一个阈值,达到阈值之后就不再指数增长,转为线性增长】
当速率达到上限就会出现网络拥堵,从而出现丢包;此时窗口大小一下子会回到最初的值,重复刚才的指数增长+线性增长,并且要动态调整阈值,阈值调整为刚才丢包的窗口的一半。
7. 延迟应答
1)延迟应答 是基于流量控制来引入的提高效率的机制
2)延迟应答:返回ACK的时间稍微晚一点,不是立即返回,此时应用程序就会有时间来消费内核接收缓冲区中的数据,使得接下来ACK返回的窗口略大于立即返回的窗口。
TCP中的连接如果出现异常,怎么办?
1)程序崩溃
① 相当于进程的异常退出。而程序退出(正常or异常)之后操作系统就会回收进程的资源,包括释放文件描述符表,这样的释放操作就相当于调用了对应socket的close;执行close就会触发FIN报文,进一步开始四次挥手。
② 所以该情况与普通的四次挥手没啥区别。
2)正常关机(通过开始菜单这种方式来关闭主机)
关机的时候系统会先强制结束所有的用户进程,和上述的进程崩溃类似,系统内核会进行文件描述符表的释放操作,从而进一步进行四次挥手。
3)断电关机(主机掉电)
非常突然,猝不及防。
① 掉电的是接收方,发送方并不知道对面已经挂了,会继续发送数据。 但是此时发送的数据就没有ACK返回,发送方就会触发超时重传;重传了几次之后仍然没有应答,此时就会尝试重置连接(通过复位报文段),但是也会失败;此时就会直接放弃连接。
【复位报文段其实就是TCP报头中特殊标志位中的RST,为1就是有效的】 (补充:特殊标志位中:PSH:向对方所要数据,希望对方给个回应; URG:跟紧急指针相关)
② 掉电的是发送方,此时接收方就只能等着。 但是接收方也不是干等,等了一段时间之后就会发送一个“心跳包”,心跳包是周期性触发的,只是一个简单的不携带任何业务数据的包,存在的意义就是确认一下对方是否还在。 如果对方不返回心跳包,说明此时对方已经挂了。
4)网线断开
情况同主机掉电类似,只不过通信双方的主机都正常,这两端各自按照上述两种情况分别进行。
(主要考查的其实是TCP)
其实就是基于UDP在应用层来实现确认应答、超时重传、引入序列号、滑动窗口(会确认都收到才滑到下一个)、流量控制、拥塞控制等等。
IP地址分为两个部分:网络号和主机号
① 网络号:标识网段,保证相互连接的两个网段(网段:网络号,局域网的身份标识)具有不同的标识;(网段具有不同标识便是不同局域网,用网络号来表示局域网)
② 主机号:标识主机,同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号;(表示不同主机)
【同一个局域网中,主机之间的网络号是相同的,但是主机号必须不同。】
在相邻的局域网中(同一个路由器(WAN口和LAN口有不同的网络号)连接的局域网),要求网络号是不同的
1)子网掩码可以划分从哪里到哪里是一个网络号。
2)子网掩码有32位,左半边都是1,右半边都是0(不会0/1混合)
3)子网掩码左半边有多少个1就表示IP地址左侧有多少位的网络号。
4)把子网掩码与IP地址按位与运算得到的结果就是网络号
(这其实是一个开放性问题,有很多角度)
站在后端开发的角度:【大纲,详细可以参考网上回答】
1)DNS域名解析
① 在浏览器输入一个网址URL后,首先要进行DNS域名解析
网络上的设备都是通过IP地址作为身份标识的,但是IP地址不好记/不好传播,此时就可以使用一串单词(域名,如http://www.baidu.com)来表示这个IP地址。
但是实质上网络的数据传输还是通过IP地址的,所以就需要把域名解析成IP地址。
所以,DNS系统功能就是把域名自动转换成IP地址。
2)封装
② 转换完成后就得到一个IP地址,浏览器就可以构造出HTTP数据报
③ HTTP数据报被交给了传输层(也就是是TCP),TCP就根据刚才的地址先建立连接(三次握手),然后再发送刚才的HTTP请求。
④ 请求被发送到网络层(也就是IP协议),IP协议将其封装成IP数据报再交给数据链路层。
⑤ 数据链路层收到IP数据报后将其封装成对应的数据帧,最终通过网卡传输出去。
3)传输:中间会经历一些交换机和路由器
⑥ 交换机 会把数据分用到数据链路层(更上层的就不再解析了),再重新封装,继续转发。
⑦ 路由器 会把数据分用到网络层(更上层就不再进行解析了),重新封装,继续转发。
转发过程涉及到路由表的匹配过程:路由器根据数据报中的目的IP在路由表中匹配,找个合适的方向发出去。(注:每次转发TTL都减1)
4)到达服务器
⑧ 到达目标服务器之后,服务器进行层层分用,一直到HTTP这一层(HTTP具体解析过程后面再说)
⑨ 服务器就会找到你想访问的那个资源,把资源构造成HTTP响应(也就是根据请求计算响应)
5)服务器把响应数据进行重新封装(同以上2)
6)响应数据在中间进行转发,回到浏览器
7)浏览器(客户端)这里再针对数据进行解析【分用】
8)最终解析出一个网页并渲染到浏览器上。