【Java EE】-网络编程(三) TCP/IP协议详解

作者:学Java的冬瓜
博客主页:☀冬瓜的主页
专栏:【JavaEE】
主要内容:应用层HTTP协议、DNS域名解析系统、传输层UDP协议,TCP协议。TCP协议的工作机制:确认应答、超时重传、连接管理、滑动窗口、流量控制、拥塞控制、延时应答、捎带应答、面向字节流地粘包问题、客户端服务器异常断电等的理解。

一、应用层

1、自定义协议

自定义协议要做的事情就是两件事:
1.明确协议数据要传输哪些数据。(根据需求分析获得)
2.明确数据组织格式。比如可以使用纯文本,或者xml标签形式,json方式,或者protobuffer(二进制)

2、知名协议

2.1、HTTP协议

HTTP协议可以传输多种类型的文件,包括HTML页面、图像、音频、视频以及其他文本文件。
HTTP协议是浏览器和服务器之间进行数据传输的协议。客户端通过浏览器发送HTTP请求,服务器通过HTTP响应返回数据给浏览器。
HTTP是一种无状态的协议,每个请求和响应之间相互独立,不会记录之前的请求和响应。

2.2、DNS协议

DNS域名解析系统:

DNS全称域名解析系统,就是我们使用的地址栏上的地址。对服务器来说,要访问的其实是服务器的IP地址,但是IP地址记起来很麻烦,于是就用一些简单的单词构成字符串表示这个IP地址。每个域名都对应了一个/N个IP地址。
【Java EE】-网络编程(三) TCP/IP协议详解_第1张图片

那么怎么将IP和域名对应呢?

最开始使用的是一个hosts文件,像哈希表一样,建立了IP和域名之间的映射关系。
后来网站越来越多,仅靠hosts文件难以维护,所以有了DNS服务器。当你访问某个域名时,就会自动请求DNS服务器,DNS服务器就去查表,然后返回给你要访问的具体的IP地址,你就可以根据IP地址访问你要访问的服务器。

域名不能重复,如何保证?

使用一级域名、二级域名、三级域名…
一级域名比如:.com.org.cn
二级域名比如:baidu

因为域名分级了,所以DNS服务器也分级了。
且IPv4对应一套域名解析系统,而IPv6又对应另一套域名解析系统。IPv4的DNS服务器大部分在美国,所以我们才大力发展IPv6对应的DNS服务器。

二、传输层

传输层是操作系统内核实现好了的,但是程序员可以通过系统提供的 Scket API完成网络编程。 传输层最著名的协议就是UDP和TCP。

端口:
端口范围范围是0~65535(2^16-1),0 ~ 1023叫做知名端口,分配个给广泛使用的应用程序。

程序员需要记住的数字:
1个字节:8个bit位,0~255 (0 ~ 2^8 - 1),或者-128 ~ +127( -2^7 ~ 2^7-1)
2个字节:16个bit位,0~65535 (0 ~ 2^16 - 1),或者-32768 ~ +32767( -2^15 ~ 2^15-1)
4个字节:32个bit位,0~ 42九千多万(0 ~ 2^32 - 1),或者 -21亿~ +21亿( -2^31 ~ 2^31-1)

1、UDP协议

【Java EE】-网络编程(三) TCP/IP协议详解_第2张图片
【Java EE】-网络编程(三) TCP/IP协议详解_第3张图片

  • 16位端口:
    UDP协议和TCP协议的报头中都包含 源端口 目的端口。
    在两种传输层协议的报头中,端口都使用16个bit位表示,也就是两个字节。
  • 16位UDP长度:
    要求整个UDP数据报的长度不超过2^16(0 ~ 65535)字节(b),约等于不超过64kb。
    如果数据报很大,超过64kb,可以采用两种方法:1>发送方在应用层对应用层数据报进行拆分发送,接收方解析时再进行重组。2>使用TCP
  • 16位校验和:
    校验数据传输是否正确。数据内容相同,校验和一定相同;数据内容不同,校验和也可能相同,但是概率很小,可以忽略不计。

在网络传输数据中,生成校验和的知名算法有:
CRC: 将设定的初始值和数据进行合并,然后做除法运算,得到新的值,重复操作,最后得到结果。
MD5 : MD5算法很强大,应用广泛,1>生成校验和;2>作为计算hash值的方式;3>加密。这源于MD5的特性:1>定长;2>冲突概率小;3>不可逆
SHA1: 它也有定长特性,可以用于hash值的计算。

2、TCP协议(重点)

【Java EE】-网络编程(三) TCP/IP协议详解_第4张图片

  • 4位首部长度:
    一个TCP报头,长度是可变的。不像UDP报头 固定8个字节。首部长度就描述了TCP报头的长度,不包含数据部分。4位首部长度,即4个bit位,可以表示0~15的数。
    这个首部长度的值的单位是4字节(比如值为0001就代表4个字节),我们看TCP报头可以发现,选项以上的内容为20字节,如果选项的部分为0,那么首部长度就应该是5(5x4=20)。

  • 40字节选项:
    选项部分用于TCP功能或数据的扩展,提高性能。
    如果首部长度是15,那么选项=首部长度x4-20。所以,选项此时就是40字节。

  • 6位保留位:
    保留位置,便于以后方便扩展。

  • 6位标志位:
    URG:紧急指针是否有效
    ACK:确认号是否有效
    PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
    RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
    SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
    FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段

  • 16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光包含TCP首部,也包含TCP数据部分。和UDP的校验和一样。

  • 16位紧急指针:标识哪部分数据是紧急数据。

TCP对数据提供的管控机制,主要体现在两个方面:安全和效率
接下来我们来理解TCP内部的工作机制,这其中就有ACK,SYN,FIN,窗口,序号,确认序号等信息,帮助我们全方面的理解。

2.1、确认应答

确认应答:TCP传输数据时,主机A作为发送方给主机B发送数据,B收到数据后,给A返回一个 ACK,确认B已经收到A发送的数据。

在网络传输中,如果不做特殊处理,可能会存在数据后发先至的问题
比如A给B发送数据本来的情况是:A发B:今天周六,你写代码没?B回A:有。A发B:你找到女朋友没?B回A:没有。
【Java EE】-网络编程(三) TCP/IP协议详解_第5张图片
引入编号后,即使出现后发先至的情况(程序上,用户看到的界面则不会发生), 也不会有上述信息歧义的问题。如下图的情况:
【Java EE】-网络编程(三) TCP/IP协议详解_第6张图片

  • 32位序号和32位确认序号:
    在TCP中,任何一条数据都是有序号的,包括应答报文。应答报文除了有序号,还有确认序号,普通报文的确认序号字段里的值则无意义,因此可以理解为普通报文无确认序号。
    那么怎么知道报文是不是应答报文?在6位标志位里的ACK值为1则表示这是确认序号,那么报文就是应答报文;为0则表示确认序号无意义,只有序号,因此是普通报文。

在TCP协议中,因为是面向字节流,所以序号并不是按照一条消息,两条消息来编号,而是按照字节的方式来编号的,如下图:

假设第一条数据是1000字节,那么数据第一个字节序号就是1,第二个是2…由于1-1000的数据都属于同一个TCP数据报,所以此时报头中序号是1。接下来假设第二个数据报也是1000字节,第二份数据的报头中序号就为1001,然后…。TCP知道TCP数据报第一个节点的序号,再根据TCP数据报的长度,就可以很容易得到了TCP数据报中的字节序号。
注意:
1>这个字节序号不一定从0开始,是在客户端和服务器建立连接关系时协商确定。
2>确认序号的取值是收到的最后一个数据的序号加1(表示这个序号之前的数据都已经收到,接下来就索要以这个序号开头的数据报)。

【Java EE】-网络编程(三) TCP/IP协议详解_第7张图片

2.2、超时重传

在上面确认应答机制中,我们讨论了通过编号解决后发先至,通过确认应答保证TCP传输的可靠性,都是数据可以正常发送接收的情况,但是如果丢包了,那就又会出现问题!

丢包:1>丢失数据 2>丢失确认应答(ACK)
【Java EE】-网络编程(三) TCP/IP协议详解_第8张图片

在TCP中,是这样解决丢包的:规定一个超时时间,如果对方还没响应,就重新发一次。

如果是丢失数据,那重传一次完全没问题,但是如果是丢失ACK,那么接收方就受到了两份一样的数据,这是否产生问题?

在TCP中,进一步解决丢失ACK,重传后,接收方收到两份数据的问题:TCP传输,在接收方存在去重操作。
具体情况接着往下看,在说之前我们先来搞清楚什么是缓冲区:在TCP里的每个 Socket对象,都有一个接收缓冲区(也有一个发送缓冲区),主机B接收到主机A发送的数据时,其实是B的网卡读到数据了,然后把这个数据放在对应的Socket缓冲区中,然后后续应用层通过inputStream流,进一步通过read读取缓冲区的数据。缓冲区可以看成是一个阻塞队列(有序的),在阻塞队列中的数据等待应用层的读取。
解决
如果A给B发数据,B回ACK时ACK丢失,那么A给B重新发送这份数据,这时候,这两份相同的数据都会在 B的接收缓冲区中,B通过TCP的传输时的字节序号对比就可以很容易发现这两份数据重复,从而将后一份数据之间丢弃。因此就保证了应用程序调用read读到的数据,一定是不重复的数据。

同时,TCP使用这个接收缓冲区,对收到的数据进行重新排序,从而让应用程序 read的数据是保证有序的!即在客户这里显示的信息就是有序的!

注意:由于由于去重和重新排序机制的存在,发送方只要发现丢包(包括丢数据或丢ACK),就会重新发送数据,即使数据重复,数据顺序乱了,在缓冲区中都可以解决问题!

解决了丢包一次的问题,那我们想象丢包多次的问题:在TCP中,如果丢包多次,那么就会重传多次,达到一定次数时,会尝试重置连接,如果重置连接还是失败,就彻底断开连接了。通过这样的方式达到"止损"的目的。
而且,重传时间会随着重传次数的增加 超时时间也会延长,从而降低重传频率,节省资源。

注意:TCP可靠性是通过 确认应答+超时重传 的机制实现的。
其中:确认应答描述的是数据顺利传输的情况,超时重传描述的是数据传输失败的处理,二者相互配合,共同支撑TCP的可靠性

2.3、连接管理(重点)

客户端和服务器通过三次握手建立连接,通过四次挥手断开连接。

2.3.1、三次握手

三次握手的作用:
1> 保存通信双方之间的信息,彼此之间相互认同
2> 验证双方的发送能力和接收能力是否正常
3> 在握手的过程中,通信双方来协商一些重要参数(比如传输的TCP数据的序号是否从1开始)

接下来我们来理解理解三次握手作用1和作用2:
作用1:建立彼此之间相互认同。这个建立连接的过程,就像两个人恋爱建立关系的场景一样,如下图:
“三次握手” 本质上是 “四次交互” 。通信双方,各自给对方发送"建立连接"
的请求,同时,再各自返还给对方一个ack,这里是有四次信息交互,但是中间两次交互合并变成一次交互,所以变成三次握手。
【Java EE】-网络编程(三) TCP/IP协议详解_第9张图片

作用2:验证双方的发送能力和接收能力 还是上述例子:再加上男女双方都是程序员这个条件。
当女方收到男方发来的表白时(第一次握手):女方是知道男方的数据发送功能完好,并且知道自己接收数据的功能完好;男方什么都未知。
当男方收到女方发来的表白时(第二次握手):男方知道自己的消息已经被女方收到,且自己够接收到女方发来的数据,所以男方的发送和接收功能完好,女方的接收和发送功能也完好。所以此时男方知道了双方的发送河接收信息的功能都完好;但此时女方还不知道自己发送功能是否完好,男方接收功能是否完好。
女生收到男生发的好啊(第三次握手):女生也可以确认双方通信完好了。

为什么不使用2次握手建立连接?或者4次握手?
如果使用2次握手,那上述例子的最终结果是:男方知道双方 发送和接收信息能力完好,但是女方不知道自己发送功能是否完好,男方接收功能是否完好。
如果使用四次握手,那中间的两次发送是两次封装分用,比一次封装分用成本更高!

三次握手图:ACK=1是标志位,Ack=123457是确认应答数据。
【Java EE】-网络编程(三) TCP/IP协议详解_第10张图片
可以简化为下图:
【Java EE】-网络编程(三) TCP/IP协议详解_第11张图片

2.3.2、四次挥手

断开TCP的连接采用四次挥手的方式。

四次挥手的场景和情侣分手的场景很像,如下图:
【Java EE】-网络编程(三) TCP/IP协议详解_第12张图片
为什么中间两步不能合并成一步操作呢?四次挥手断开连接的图可以简化为下图:
在建立连接时,使用的是三次握手,将中间两步和并成一步解决(为减少成本),但是断开连接这里却不能将中间两步合并,因为中间两步中ACK和FIN的时机是不一样的!!!

  1. 在建立连接时:可以将中间两步和并,是因为这两步时机相同。因为这三次握手是纯操作系统内核操作的;服务器的操作系统内核接收到 SYN后,立即返回 ACK和SYN给客户端,在程序员这里其实是感知不到的。
  2. 在断开连接时:不能将中间两步合并,因为这两步时机不同。FIN的发起,则不是由内核控制的,而是由应用程序控制,socket的close方法(进程退出),才会触发FIN。所以服务器收到FIN后,会立即返回ACK,但是等一会在应用程序中调用Socket的close时才会继续返回 FIN给客户端。

【Java EE】-网络编程(三) TCP/IP协议详解_第13张图片

2.3.3、TCP建立连接和断开连接状态

  • 建立连接状态:
    1> LISTEN 服务器的状态,表示服务器已经就绪,客户端可以随时来连接
    2> ESTABLISHED 表示自己已经和对方建立连接,客户端服务器都有,就表示建立连接完成!
  • 断开连接状态:
    1> CLOSE_WAIT 出现在被动发起断开连接的一方,如果客户端主动发起,CLOSE_WAIT出现在服务器,如果服务器主动发起,CLOSE_WAIT出现在客户端。 等待关闭,应用程序中调用Socket的close,销毁Socket。
    2> TIME_WAIT 出现在主动发起断开连接的一方。假设是客户端发起的断开连接,如下图:在TIME_WAIT前,已经完成了第四次挥手(客户端给服务器发送ACK),但是ACK还没有到服务器,所以客户端等待一会。如果客户端在等待的过程中,其实这个ACK已经丢包,无法到达服务器了,服务器根据超时重传的机制,会重新发送FIN 给客户端,因为客户端处于TIME_WAIT状态,此时客户端就可以再次发送ACK给服务器。
    TIME_WAIT具体等待 2MSL(MSL是在互联网上,两个之间数据传输消耗的最大时间,MSL通常情况是60s)。如果客户端等待 2MSL后,还没收到服务器发来重传 FIN,就认为之前发送的ACK已经到达服务器,就不再等了,可以关闭客户端了!

【Java EE】-网络编程(三) TCP/IP协议详解_第14张图片

注意:确认应答、超时重传、连接管理为TCP传输的可靠性提供了支持

2.4、滑动窗口

TCP协议相比于UDP引入了可靠性,但是也因此降低了效率,而滑动窗口就是为了相对地提高效率,为可靠性造成的效率低做的补救措施。

滑动窗口本质上是降低了确认应答,等待ACK消耗的时间。
(进行IO操作的时候有两种情况:1>等待 2>传输数据)

【Java EE】-网络编程(三) TCP/IP协议详解_第15张图片

【Java EE】-网络编程(三) TCP/IP协议详解_第16张图片
【Java EE】-网络编程(三) TCP/IP协议详解_第17张图片

滑动窗口使用批量发送一组数据的方式,用等待一份ACK等待的时间等待多份ACK,这种是数据传输正常的情况,如果出现丢包,那怎么办?

1> 数据丢了 :发送发收到连续3次相同的ACK,就重发这份ACK对应的数据。在下图中1000-2000的数据丢了,接下来2001-3000到达主机B后,B给A返回的确认序号仍为1001(即向A索要1001-2000的数据),A收到B返回的3次1001ACK后,A就知道B未收到1001-2000的数据,就将这一份数据重发给B了。此时B已经收到1000-7000的数据,所下一个ACK就B向A从7001开始索要数据了。
【Java EE】-网络编程(三) TCP/IP协议详解_第18张图片
2> ACK丢了:不需要做任何处理,因为一组中包含多个ACK,即使丢了一两个,只要不是全丢,由于滑动窗口的滑动和 ACK确认序号的含义(这个ACK序号之前的数据已经到达),仍可以继续往后执行。
比如A给B发送数据1-5000,窗口大小是6000,那么如果是B返回给A的1001这个ACK丢了,但是只要2001(或3001…6001)ACK返回给A,那么就代表2001之前的数据B已经收到,所以A不需要超时重传。
【Java EE】-网络编程(三) TCP/IP协议详解_第19张图片

  • 快速重传:发送数据是丢失数据,如果此时传输数据比较密集,是按照滑动窗口的方式传输,此时按照 “快速重传” 来处理数据丢了。
    超时重传:发送数据时丢包(包括数据丢和ack丢),如果此时传输数据稀疏,不再按照滑动窗口的方式传输了,那就按照超时重传的方式解决丢包问题!
  • 16位窗口大小:窗口大小并不是固定的64kb(2^16-1),TCP在选项中引入了扩展因子,来扩大窗口大小。比如扩展因子是1,那十六位窗口大小就向左移1位,64kb->128kb。

2.5、流量控制

在滑动窗口的基础上,做的操作。

滑动窗口,窗口大小越大,传输效率越高(一份时间,等待的ACK越多),但是窗口效率还得看接收方的最大处理能力来控制,发送方的发送速度,不能超过接收方的处理能力。

流量控制:根据接收方的处理能力,来协调发送方的发送速率

接收方的处理能力:用接收缓冲区剩余的空间来表示接收方的处理能力。

当接收方窗口大小较大时,发送方会增大发送速率;接收方窗口大小较小时,发送发会减慢发送速率。
如果接收方缓冲区无剩余空间了,窗口大小就为0,那么发送方暂时不再发数据,而是定期给接收方发送窗口探测,等接收方把缓冲区的数据消耗了,空出位置后,发送方发送窗口探测后,接收方返回一个ACK,发送方就再根据ACK设定窗口大小。
【Java EE】-网络编程(三) TCP/IP协议详解_第20张图片

2.6、拥塞控制

在滑动窗口的基础上做的操作。

流量控制和拥塞控制共同决定发送发的窗口大小,取二者中较小的。

流量控制描述的是接收方的处理能力对发送发窗口大小的控制;
拥塞控制则是网络中中间节点的处理能力(类比木桶原理)

拥塞控制解析:拥塞窗口(尝试以多大的窗口进行发送),随着传输轮次的改变,窗口大小在不断改变。不丢包时,窗口大小在增长,当丢包时,窗口大小瞬间变小,然后再试探,最后达到动态平衡的情况。
【Java EE】-网络编程(三) TCP/IP协议详解_第21张图片

2.7、延时应答

在滑动窗口的基础上做的操作。

在滑动窗口的基础上,接收方收到数据时,延时返回ACK,在延时过程中,接收方把接收缓冲区的数据先消耗一些,这样接收方的剩余空间就大,返回给发送方的ACK中的信息中窗口大小信息就大,发送发接收到ACK后,指定的窗口大小就大,那么发送方的发送速率就快。
【Java EE】-网络编程(三) TCP/IP协议详解_第22张图片

2.8、捎带应答

在延时应答的基础之上做的操作。

【Java EE】-网络编程(三) TCP/IP协议详解_第23张图片

三次握手是一定会合并的,这里的延时应答和四次挥手(中间两步合并的)的情况相似,在四次挥手中,如果应用程序执行到close和B返回给A一个ACK的时间间隔很小很小,也是有可能合并ACK+FIN的。而这里是因为B延时应答,所以为中间两步合并提高了更大的概率。
捎带应答的原则是能合并则合并。

2.9、面向字节流

面向字节流存在"粘包问题":由于TCP是面向字节流的,所以读数据时的个数是随机的,这样就可能导致发送的两份数据连在一起,导致一次读到的可能是半份应用层数据报,或者各半份应用层数据报。

解决办法:
1> 在每份应用层数据报后加\n作为标识符(标识符得是数据中不存在的);
2> 在应用层结构中约定好每个包的长度
【Java EE】-网络编程(三) TCP/IP协议详解_第24张图片

2.10、异常情况

传输过程中因不可抗的因素,出现了异常。

1.进程崩溃
2.主机关机(正常关机)
3.主机断电
4.网线断开

注意点1:1出现时,进程对应的PCB没了,PCB中的文件描述符表就没了,相当于Socket调用close关闭了,因此会正常执行四次挥手,只是此时接收方不是返回FIN给发送方,而是返回RST给发送方,从而发送方不需要进入TIME_WAIT状态,而是收到RST立即释放资源并尝试重新建立连接。2出现时,关机前先关进程,也是会四次挥手。
注意点2:3和4出现时,就无法完4次挥手。
如果接收方断电了,发送方在发送数据,发送发无法收到接收方发来的ACK,然后超时重传,仍然无法收到ACK,重传几次尝试重置TCP连接(复位报文段RST),连接不上A就彻底放弃和B连接了。
如果发送方断电了,接收方会隔一段时间给发送发发送一个消息"心跳包",来确定发送方是否还在工作。如果发送方无反应了,接收方就会断开连接。

2.11、小结

  1. 确认应答,超时重传共同保证了TCP可靠性。
  2. 三次握手为TCP的建立连接提供支持,四次挥手为TCP的断开连接提供支持
  3. 流量控制、拥塞控制、延时应答都是在滑动窗口的前提下做的策略;捎带应答是在延时应答的基础上做出的策略
  4. 处理粘包情况可以加标识符或指定应用层数据报大小;理解清楚异常有哪些,导致的情况有哪些。

3、UDP和TCP的对比

TCP:保证数据可靠传输
UDP:性能高

UDP应用场景:
1>同一个机房内部的服务器之间通信(丢包概率小,且即使丢了也没啥事)
2>UDP天然支持广播。
     IP地址中有一种特殊的地址叫做"广播IP",通过UDP往
     广播IP上发送数据报,此时这个IP的局域网内的所有设备都能收到广播!


游戏需要的传输层协议:在游戏上既需要可靠,有需要效率,但是UDP牺牲了可靠换来了效率,TCP牺牲了效率换来了可靠,因此都不符合游戏的应用场景,在游戏中,传输层协议需要一个效率和可靠性都兼备居中情况。

三、网络层

网络层主要做两件事:1>地址管理 2>路由选择
网络层最知名的协议就是IP协议。

1、IPv4协议

【Java EE】-网络编程(三) TCP/IP协议详解_第25张图片

  • 4位版本号:只有两个取值4和6,代表IPv4和IPv6。

  • 4位首部长度:和TCP的4位首部长度一样,描述了IP报头长度,是可变的,且用法相同。

  • 8位服务类型(TOS):说是8位,只有4位有效,这四位中只有一位可以是1,其它位是0。4位就表示IP协议中的四种工作模式。四种工作模式分别为:最大延时、最大吞吐量、最高可靠性、最小:成本,只能选四者中的一个。

  • 16位总长度(字节数):描述了一个IP数据报的长度,报头+载荷。可以知道因为16位的限制,IP数据报最长是64kb。那如果超过64kb,如何处理? IP协议支持对数据报的自主 拆分和组装。 传输层协议UDP则需要程序员手动在代码中完成拆分和组装。
    实际的IP数据报的长度并不一定达到64kb,往往会更小,这取决于数据链路层。

  • 16位标识,3位标志,13位片偏移:这几个字段都是辅助拆包,组装提供的信息。同一个数据拆成的多个包的16位标识符是一样的,3位标志位描述了结束标志(就是在最后一个包中加上结束标志),13位片偏移标识了同一个数据拆成的多个包的先后顺序。

  • 8位生存时间(TTL):一个数据报在网络上能够传输的最大时间(这个时间指的不是"秒"而是"次数"),这个数据报构造出来就有一个初始值,在传输中每经过一个路由器转发,TTL-1,如果TTL=0了数据还没到达,这个数据就丢包了,且这个包不可能到达对面。

  • 8位协议:描述了载荷部分内容是属于哪一个传输层协议的,如UDP,TCP…

  • 16位头部校验:这里只对IP报头首部校验,载荷已经在之前由传输层校验了。

  • 32位源IP,32位目的IP:根据源IP和目的IP规划路径。

接下来我们进一步思考和理解:

IPv4的IP只有32位,表示的数只有0-42亿。为了解决IP不够用的场景就有了一些列的方法:
1> 动态分配地址。
2> NAT网络地址转换。
3> 使用IPv6从根源上解决问题。

1.1、NAT网络地址转换

使用NAT后,IP可以不用指一个设备,而是代指一批设备。比如你的校友一同使用你的学校这个IP,而每个同学之间使用端口号区分开。

在NAT的背景下,把IP分成了两大类:
内网IP(私网IP):(10.* ) (172.16.* -172.31*)(192.168.*)
外网IP(公网IP):剩下的为公网IP

NAT要求,公网IP是唯一的,私网IP在不同的局域网中可以重复出现。

如果私网设备想要访问公网设备,就需要对应的NAT设备(路由器),把IP地址进行映射(用路由器的IP替换要访问公网的私网IP),从而完成网络访问。(见下图),同时,此时服务器这边的响应数据的目的ip就变成运营商路由器了,运营商路由器收到响应后,再根据私网ip对应的端口转发回响应。
具体操作是:路由器会维护一张NAT表,记录私网IP和端口对应的公网IP和端口,以便于在路由器收到响应后,能正确响应给相应的私网IP和端口。
反之公网的IP不能访问私网IP,私网IP之间也不能相互访问
【Java EE】-网络编程(三) TCP/IP协议详解_第26张图片

2、IPv6

IPv4使用4个字节(32位)表示IP地址,表示范围是0~42亿9千万。
IPv6则使用16个字节(128位)表示IP地址,表示范围并不是IPv4的4倍,而是42亿 * 42亿 * 42亿 * 42亿。

注意:IPv6和IPv4不兼容

3、地址管理

3.1、IPv4地址的组成

网络号:标识网段(局域网),保证相互连接的两个局域网具有不同的标识(要保证相邻的两个局域网的网络号不同)。
主机号:标识主机,同一个局域网内,主机之间具有相同的网络号,但是必须有不同的主机号。

注意:划分出网络号和主机号的目的就是为了组网。

【Java EE】-网络编程(三) TCP/IP协议详解_第27张图片
【Java EE】-网络编程(三) TCP/IP协议详解_第28张图片
【Java EE】-网络编程(三) TCP/IP协议详解_第29张图片

3.2、子网掩码

子网掩码:一个IP地址,怎么区分哪些是网络号,哪些是IP号? 通过子网掩码
在这里插入图片描述
这个图中前三个字节的每一个比特位(24个比特位)都是1,代表前面的这三个字节表示网络号,后一个字节的8位比特位为0,表示后一个字节表示主机号。

但注意:网络号的表示并不一定就是前3个字节!具体要看子网掩码!

特殊IP:
【Java EE】-网络编程(三) TCP/IP协议详解_第30张图片

4、路由选择

路由选择就是规划路径。

路由选择,核心思路就是问路!
每一个路由器都会保存周围一定设备的信息(发送方的IP和端口,以及接收方的IP和端口,使用哈希表建立关系)
每次有一个IP 数据包经过路由器,它就会查找哈希表以确定下一步数据包发向哪里,如果哈希表中没有目标IP地址的匹配项,路由器将使用默认路由将数据包转发到预定的下一个路由器。即去一个地方时,如果找不到具体的路,就根据大体方向走过去再问路。

这个数据包每经过一个路由器,TTL(8位表示,最高2^8-1)TTL-1,如果数据包的TTL-0了,那就永远也到不了接收方那里!就被丢弃了。

四、数据链路层

考虑两个相邻节点数据的传输。(通过网线/光纤/无线直接连接的两个设备。 数据链路层最知名的协议就是 “以太网”。

1、以太网数据帧

以太网数据帧=帧头+载荷+帧尾。(0800类型载荷为完整的IP数据报)
【Java EE】-网络编程(三) TCP/IP协议详解_第31张图片
注意:此处目的地址和源地址并非IP地址而是一个mac地址,mac地址和IP地址完全独立,是另一套地址体系。
mac地址使用6字节表示,数量比IPv4大很多(有两百八十亿万多),因此每个设备都能分配到一个mac地址,这个地址不是动态分配的,是网卡 出场时就被设置好的。
【Java EE】-网络编程(三) TCP/IP协议详解_第32张图片


IP地址和mac地址是相互配合,共同完成数据传输的。
IP地址是网络层协议,关注的是源发送方的IP和目的接收方的IP,从而规划路径;
而mac地址是数据链路层以太网协议的地址,从而考虑相邻节点数据的传输,是当前转发设备的mac和传输到下一个节点的 mac地址。

2、以太网数据报的类型

数据链路层中的另外的协议:ARP协议,通过这个协议,可以在路由器/交换机 里创建一个关于IP和mac的哈希表,从而在当前设备根据IP地址找到mac地址。
【Java EE】-网络编程(三) TCP/IP协议详解_第33张图片

3、数据链路层 MTU

下图为以太网数据帧,载荷的长度即为MTU,载荷具体多长,和物理介质有很大关系,也和数据链路层使用的协议有很大的关系。

IP的分包组包通常不是使用IP的最大报文长度64kb来分开的,而是通过数据链路层的MTU。因为MTU一般都比64kb小。
【Java EE】-网络编程(三) TCP/IP协议详解_第34张图片

你可能感兴趣的:(JAVAEE,网络,java-ee,tcp/ip)