关于java:你需要知道的TCPIP

7次阅读

共计 9297 个字符,预计需要花费 24 分钟才能阅读完成。

前言

TCP/IP 协定 是网络通信的基石,TCP/IP 协定 不是只有 TCPIP 协定,它是整个网络通信中所有协定的简称。

维基百科:TCP/IP 协定簇)

维基百科:OSI 模型

# TCP/IP 参考模型维基百科
https://zh.wikipedia.org/wiki/TCP/IP%E5%8D%8F%E8%AE%AE%E6%97%8F
# OIS 参考模型维基百科
https://zh.wikipedia.org/wiki/OSI%E6%A8%A1%E5%9E%8B

<img src=”http://oss.mflyyou.cn/blog/20200801104517.png?author=zhangpanqin” alt=”image-20200801104517510″ style=”zoom:50%;” />

图片来自《图解 TCP/IP 与 OSI 参考模型》中 TCP/IP 协定分层模型

OSI 参考模型(七层)是个实践模型,理论咱们用的是 TCP/IP(四层)模型。不过咱们能够通过 OSI 参考模型 来学习 TCP/IP 模型。

应用层:应用程序通信细节的协定,比方罕用的 HTTP

传输层:次要是负责两个节点之间数据传输,通信标识是 port 端口号。

网络层:地址治理和路由抉择,在两点之间找到一条最佳的通信路线,通信标识是 IP

数据链路层:负责物理层面链接的通信(同一个网段内)。也就是局域网中通过交换机链接的节点。通信标识是 Mac 地址,网卡出厂自带的标识。

物理层:将链路层的数据帧(字节流)转换为电压或光信号流传。

网络通信能够做什么呢?

redisson(一个操作 redis 的 java 库),就是应用的 netty 来做网络通信连贯 redis 服务的。

微服务中的服务发现和通信,就须要你相熟网络通信。

你要是在通信行业,那就不是理解了,你连协定的标准都得很分明,不然路由器你都整不进去,还说什么 5G

作为一个 Java 后端开发,次要是开发偏利用层面的程序,离底层绝对比拟远,熟练掌握即可,如果当前做通信行业的时候,你也肯定会进一步学习的相干细节的。

TCP/IP 你不理解,也不会有多大问题,CRUD 还是没有问题的。然而你理解了之后,日常开发定位和解决问题方面有很大助力,总之学习 TCP/IP 是一个重要不紧急的事件,依据本人指标和档次安顿。

本文内容

  • 局域网中各节点怎么通信
  • 介绍 IP,ICMP,ARP 协定在网络层的作用及路由表的作用,及网段划分,子网掩码、网关的作用
  • 介绍交换机和路由器的作用
  • 介绍 TCP/IP 三次握手和四次挥手,TCP 中通信状态的作用,滑动窗口
  • 介绍 tcp 包格局,ip 包格局,链路层 数据格式

交换机与路由器

交换机

维基百科:交换机)

交换机上有多个端口(不是 port)供计算机连贯,替换机会保护端口与连贯这个端口的 PC 的 Mac 地址映射表。当交换机承受到数据的时候,会依据目标 Mac 地址,发送到对应的端口上,而后通过网线发送到目标 PC。

交换机链接多个电脑组成一个局域网,交换机链接交换机又能够组成一个更大的局域网。

比方 A、B 交换机各有 100 个端口,A 链接了 99 个 PC,而后 B 交换机链接 99 个,再将其中的一个端口 A/B 之间相互连接组成一个更大的局域网。

路由器

维基百科:路由器)

路由器工作在网络层,次要用于将一个网段数据包转发到另一个网段内。路由器上也会有个几个 LAN 口 (Local Area Network,局域网),用于建设局域网。还会有一个 WAN(Wide Area Network,广域网),连贯运营商的网络。

路由器也具备交换机的性能,只是 LAN 口 比拟少,能够接入的电脑比拟少。

PC 或者 手机 连贯无线路由器时也会给 PC 调配一个 局域网 IP,子网掩码,网关等。

我住的中央的网络拓扑图如下:

当手机与电脑通信的时候,理论通过 LAN 口走局域网通信。

当手机拜访 维基百科 时,理论是通过路由器跳入到光猫网段,再通过光猫跳入到小区运营商的网络,… 到维基百科的服务器上。

只有须要有 IP 地址的设施(光猫,路由器,PC,手机)都须要有网卡,网卡出厂自带有 Mac 地址。IP 和 Mac 地址的作用后文中会介绍。

交互机和路由器的区别

<font color=red> 这部分内容是我本人的了解,我没有在网上找到材料佐证,请审慎看待 </font>

其实交换机和路由器硬件差异不大,只是硬件上的软件决定了它能做什么。

2 层交换机上的软件(只有数据链路层)可能只做解析帧,拿到 mac 地址,而后查找以后交换机的端口对应的 mac 地址,而后从对应的端口传递过来。

路由器(有网络层和数据链路层),当拿到数据包的时候,发现目标 mac 地址不是本人,就会将数据包通过 LAN 口发送进来。

当发送的数据包的 目标 MAC 地址 是以后路由器上 MAC 地址,路由器就会对其解包,拿到数据包 目标 IP,而后依据 目标 IP 匹配下一跳 mac 地址,封包为新的帧数据发送进来。

TCP/IP 通信

从发送端发送数据的时候,数据通过每层的封包,经物理层传送到接收端。接收端收到数据包,一层一层进行拆包,而后将数据数据发送给我接收端的应用层的应用程序。

通常咱们说的第一层就是 物理层 ,第二层是 链路层 ……

数据链路层

源 MAC 地址 就是发送端的 MAC 地址,指标 MAC 地址不是最终的 MAC 地址,是下一跳节点的 MAC 地址。

类型 指的是这个以太网帧中的 数据 是何种类型的数据,比方 IPV4,IPV6。而后调用对应的接口进行解决。

数据链路层传输的帧是有大小限度的(64-1518 字节),能传输的数据的最大值就是 最大传输单元,简称 MTUMaximum Transmission Unit。这个值在以太网中通常是 1500。

# 查看网卡对应的 MTU
ifconfig -a
netstat -i

网络层

网络层次要以 IP 协定为主,也有 ICMP,ARP(在 TCP\IP 模型 中,arp 属于网络层。在 osi 七层模型arp 数据链路层。)。

DNS

IP 是网络层通信的标识。然而 IP 不容易记忆,所以呈现了 域名

拜访 DNS 能够将域名解析为 IP

能够在本地配置 host , 定义域名和 IP 对应关系,这样就不必解析了。

也能够在电脑配置 DNS 解析时拜访的 ip,这样域名解析时就会拜访这个服务。

<img src=”http://oss.mflyyou.cn/blog/20200801182357.png?author=zhangpanqin” alt=”image-20200801182357581″ style=”zoom:50%;” />

# 解析域名的 ip
dig www.mflyyou.cn

IP 根底

IP 地址 又能够分为 IPV4IPV6,目前应用比拟广的是 IPV4,所以只介绍 IPV4

IP 地址 由 32(2 进制)位组成,32 位被 . 分为了四组。每组 8 位,十进制示意就是 xxx.xxx.xxx.xxx(xxx 取值在 0-255)。

IP 地址 网络地址 (网段)和 主机号

同一个网段的电脑用 2 层交互机相连,而后就能够局域网通信了。

同一个网段内,主机号不能反复,反复主机号的电脑不能上网。

为了便于辨别出 IP 在那个网段,引入了 子网掩码(netmask)。IP 地址与子网掩码按位与计算能够得出网段,32 位 中取出网段所在的位,残余就是主机号能获得值。

IP 中主机号全为 0 就是网段,全为 1 就是播送地址。这两个是不能被调配给电脑的。

IP:192.168.202.116

子网掩码:255.255.252.0

网段为:192.168.200.0

播送地址为:192.168.203.255

IP:192.168.201.56

子网掩码:255.255.252.0

网段为:192.168.200.0

播送地址为:192.168.203.255

ICMP

网络层是不牢靠传输,发送失败的数据包,网络层是不会再发一次数据包,然而会有 ICMP 包回复通知你发包到底是什么问题。传输层 能够依据 ICMP 来判断是否须要重发包。

ARP

ARP 用于 IP 的 对应的 MAC 地址。

目标 IP 在路由表中查问下一跳的 IP, 在查问这个 IP 对应的 mac 地址

查问的这个 IP 是以后网段内的 ip,它会通过播送地址发送给以后网段内所有主机,收到这个协定的主机会判断是否是以后主机,是的话就会复原以后 ip 对应的 MAC 地址。

通信过程剖析

当我在浏览器输出 wwww.mflyyou.cn 的时候:

1、先解析域名(DNS)www.mflyyou.cnIP(目标 IP: 47.104.168.20)

2、将目标 IP 与本地路由表中的子网掩码进行按位与,计算出网段与 Destination 匹配,看哪个匹配度更高,走哪个条目。都没有匹配到走默认条目(0.0.0.0)

# 查看路由表
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.31.1    0.0.0.0         UG    100    0        0 eth0

3、而后用 arp 查问(有缓存可不查,走缓存)192.168.31.1 对应的 mac 地址

4、数据链路层封装以太网帧数据包中的目标 MAC 地址址就是 192.168.31.1 对应的 mac 地址,而后将数据帧发送到下一个节点(这也就常说的下一跳,数据包发送只是找到以后接节点的下一个节点)

5、到下一个路由器节点,路由器解包,看是发给本人的数据包(依据帧中的目标 MAC 地址与本人的 MAC 地址比拟),不是就抛弃了;是的话就会解包拿到 目标 IP (47.104.168.20),而后在以后路由器上依据路由表查问下一跳,发送给下一个节点;。。。。直到目标服务器,或者发送的包 TTL 为 0

6、发到目标服务器的网卡上,网卡将数据复制到内核缓冲区,应用程序从缓冲区中读取数据

IP 数据格式

<font color=red>IPv4 数据结构 </font>

<img src=”http://oss.mflyyou.cn/blog/20200802000153.png?author=zhangpanqin” alt=”image-20200802000153692″ style=”zoom:50%;” />

图来自《图解 TCP/IP》

  • 版本(Version):4 bit 形成,代表以后 IP 包是哪个版本,IPv4 或者 IPv6,为 4 时示意以后是 IPv4。
  • 首部长度(Internet Header Length):由 4 bit 形成,个别 20 字节大小。
  • 标识(Identification):用于分片重组用,值雷同的属于同一个 IP 数据包
  • 标记(Flags):用于判断是否还有分片。
  • 总长度(Total Length):16 个字节,IP 数据包总的长度,最长可为 65525 字节。
  • 分段偏移(Fragment Offset):示意这个包在原来 IP 包中的地位。
  • 生存工夫 TTL(Time To Live): IP 包在路由转发中存活的工夫,被路由转发一次,次数减 1,为 0 时,数据包被抛弃。
  • 挂载协定标识(Protocol):记录数据包中 Data(理论发送的数据)是什么类型的数据,1 标识 ICMP, 4 标识 IP, 6 标识 TCP, 17 标识 UDP。依据这个挂载协定程序就晓得调用哪些接口来进行后续的解决了。

数据链路层中 以太网数据帧MTU 是 1500 字节,限定了 IP 数据包最大为 1500 字节。而后去掉 IP 包首部 20 字节,个别 IP 数据包发送的数据为 1480 字节。

当咱们发送一个 3058 字节的 IP 数据包时,这显然大于了数据链路层的 MTU(1500 字节)。所以网络层会对大于链路层 MTU 的数据包进行分片。拆分一个一个的 1500 的数据包发送接收端,接收端接管到这三个包,在汇聚成一个实现的,在调用传输层接口。

# 会发送 3050 字节数据与 8 字节的 ICMP 首部,这个命令会总共发送 ip 数据大小 3058 字节。ping -s 3050 www.mflyyou.cn

<img src=”http://oss.mflyyou.cn/blog/20200801230141.png?author=zhangpanqin” alt=”image-20200801230141070″ style=”zoom:50%;” />

<img src=”http://oss.mflyyou.cn/blog/20200801230528.png?author=zhangpanqin” alt=”image-20200801230528418″ style=”zoom:50%;” />

<img src=”http://oss.mflyyou.cn/blog/20200801230423.png?author=zhangpanqin” alt=”image-20200801230423653″ style=”zoom:50%;” />

通过 wireshark 抓包能够看到,IP 数据包的首部长度占了 20 字节,理论每次发送数据为 1480 字节,最初一次发送了 98 字节。

从 Fragment 和 Identification 能够看到这三个包属于同一个 IP 数据包,并且从 Fragment offset 能将这三个包合成一个实现的网络层数据包。

传输层 TCP

TCP 是面向链接的,牢靠的,全双工协定。

面向连贯就是发送之前,须要建设一个链接通道,数据都是在这个链接中发送。

网络层 是不牢靠协定,数据发送失败是不会重发的。

TCP 协定中发送端会记录发送的那些数据包被客户端收到了。接收端承受数据之后,会回复一个 ACK 包(由数据格式中的管制位决定),确认应答号通知发送端哪些数据包接管到了。

发送端 发送了数据包之后,这个包会有一个重发倒计时,在这个倒计时内没有收到 接收端 回复 ACK 包,就会再重发一个数据包。如果是 HTTP 申请,就相当于同样的数据申请了两次。

咱们晓得领取接口都要求幂等性,有一部分起因是因为这个超时重发。发送端发送了申请,接收端解决好业务之后回复的 ACK 包超时,发送端超时重发这个申请。如果不保障接口的幂等性,那么扣钱就会扣两次。

咱们要做的就是保障这个重发 n+1 次不再扣用户的钱,个别会用一个 token 来判断是不是反复申请,反复就不走扣款解决了,间接返回曾经领取,保障接口的幂等性。或者用一个账单流水来保障幂等性。

连贯既然须要建设,那么也会有连贯断开。断开连接需单方协商好之后断开连接,不能单方面敞开而不论对方。因为建设连贯之后占用的计算机资源须要开释掉。你单方面强制断开连接开释了资源,然而对方不晓得须要断开连接,调配的计算机资源始终占用那就是不牢靠协定了。所以 TCP 有四次挥手断开连接。

全双工就是连贯两边都能够被动发送承受数据,而不是轮训拜访有没有数据达到。

TCP 数据格式

首先咱们要先理解 TCP 数据格式,能力更容易晓得 TCP 的工作原理。

<img src=”http://oss.mflyyou.cn/blog/20200802000246.png?author=zhangpanqin” alt=”image-20200802000246545″ style=”zoom:50%;” />

源端口号(Source Port)

占用 2 个字节。标识 发送端 程序的端口号,当接收端须要回复音讯的时候,须要带上这个端口号。

目标端口号(Destination Port)

占用 2 个字节。标识 接收端 程序的端口号,能够传递给监听在这个端口的程序

管制位(Control Flag)

占用 6 位,不满一个字节。标识以后 TCP 包是什么包,在通信过程中有一些特殊作用。

SYN

示意心愿建设三次握手链接,并初始化序列号。

ACK

对收到数据包的应答确认。接收端承受数据之后,会回复 ACK 包,发送端从其上 确认应答号 晓得接收端哪些数据曾经承受了。

FIN

示意没有数据发送了,心愿断开连接

PASH

接收端接管到这个数据包须要立即传递给应用层,不能期待接管更多的数据包

RET

链接出现异常,须要强制断开连接

URG

示意包中有须要紧急解决的数据

序列号(Sequence Number)

占用 4 个字节。TCP 三次握手的时候,发送端和接收端各自初始化(随机的)本人的 ` 序列号。

咱们能够这样了解,发送端发送的数据就是一个字节数组,这个数组中每个字节都有一个 序列号

发送端和接收端都有本人的序列号,并且不雷同,在三次握手的时候本人初始化,而后告知对方。

确认应答号(Acknowledgement Number)

占用 4 个字节。确认应答号 也是指的序列号,指的是冀望发送端下次发送的序列号,这个序列号(确认应答号)之前的数据曾经承受解决了。

下图是我抓包建设三次链接,而后我发送三次 1\n 数据。

三次握手,发送端通过发送 SYN 包,发送本人的初始化序列号(893189542),而后发送的每个字节都会有一个序列号。

接收端发送 ACK 包中的 确认应答号,指明这个序列号之前的数据我曾经承受了。

<img src=”http://oss.mflyyou.cn/blog/20200802205000.png?author=zhangpanqin” alt=”image-20200802205000890″ style=”zoom:50%;” />

窗口大小(Window Size)

窗口大小实用于流控的。发送端不能始终发送音讯,须要依据我的承受能力来调整发包的速率。

内核会为每个 TCP/IP 调配读写缓冲区,网卡会从这些读写缓冲区中把数据取走,而后发送。数据大抵能够分为这几类。

TCP/IP 是牢靠连贯,所以它须要记录哪些数据发送已被对方承受了(由确认应答号能够晓得),承受的数据会被淘汰掉,节俭内存空间。

窗口大小作用:接收端会通过 ACK 通知 发送端 调整窗口大小。

当窗口中的数据全都是 已发送未确认数据 时,发送端不能再发送新的数据,必须期待窗口空出地位来。

当有一个数据包被确认了,发送端就能够发送新的数据包。已发送未确认数据 会在超时的时候从新发包。

滑动窗口百度百科)

校验和 (Checksum)

占用 2 个字节。校验和 用于校验数据包是否损坏。每个数据包都一个 校验和 接收端 接管到数据之后,应用雷同的算法对数据计算出一个值,而后和 校验和 比拟,不一样阐明数据在传输过程中损坏了,接收端 会抛弃这个包,期待 发送端 从新发这个包。

TCP 中 MSS

链路层能发送的最大以太网帧为 1500 字节,MTU 为 1500。

IP 数据包能发送的最大数据 = MTU – IP 首部大小(个别 20 字节),IP 数据包超过这个 1500 字节会分片

TCP 传输数据以段(Segment)为单位。

TCP 为了防止分片,会被动将数据分片之后交给网络层。TCP 能传输的最大分段(只是数据不包含首部)称之为 Max Segment Size,简称为 MSS。

MSS = MTU – IP 首部大小 – TCP 首部大小

在以太网中 TCP 的 MSS = 1500(MTU)– 20(个别 IP 首部大小)– 20(个别 TCP 首部大小)= 1460,这个值须要依据首部计算

MSS 值在三次握手时,会通过 MTU 计算的。

TCP 三次握手建设连贯

<img src=”http://oss.mflyyou.cn/blog/20200802212532.png?author=zhangpanqin” alt=”image-20200802212532628″ style=”zoom: 33%;” />

图片来自 码出高效:Java 开发手册

为什么是三次握手建设连贯呢?很多面试官也会问。这其实是牢靠连贯的起码握手次数。

<img src=”http://oss.mflyyou.cn/blog/20200802212808.png?author=zhangpanqin” alt=”image-20200802212808724″ style=”zoom:50%;” />

图片来自 码出高效:Java 开发手册

这里还有个 全连贯队列和半链接队列 的知识点

TCP 四次挥手断开连接

<img src=”http://oss.mflyyou.cn/blog/20200802213247.png?author=zhangpanqin” alt=”image-20200802213247725″ style=”zoom: 33%;” />

图片来自 码出高效:Java 开发手册

CLOSE_WAIT 是收到对方 FIN 包之后,回复 ACK 之后进入的状态。之后不会承受数据了,进行已收数据的业务解决之后,在发送一个 ACK+FIN,进入 LASK_ACK,而后期待对方发送 ACK,超时没有等到,会重试发送(内核能够配置重试发送次数)。当你发现服务端有大量的 CLOSE_WAIT 链接,服务端的代码有问题,须要排查。

TIME_WAIT 的链接多的话,服务端能够优化,不然这个链接会占用很长时间,在高并发的时候,会导致没有资源开释的慢。

MSL 为 Maximum Segment Lifetime,在 centos 中默认值为 60s

# sysctl -a | grep tcp_fin_timeout
# 举荐小于 30,也不能太小,15-30
net.ipv4.tcp_fin_timeout = 60

阐明 A 机器链接会在 120 s 之后能力开释。这个是为了保障 B 机器 能接管到最初一个 ACK,当处于 LAST_ACK 的超时没有收到 A 发来的 ACK 的话,会重试发送一个 FIN+ACK。这个 2MSL 也是为了最大限度保障 B 机器失常敞开。

三次握手建设连贯 四次挥手断开连接 须要联合抓包工具本人剖析一下,了解会更粗浅。

网络抓包

Wireshark 抓包剖析是很厉害的,mac oslinux 都有命令行程序 tshark,能够在服务器用 tshark 抓包,拿到本地来剖析。

抓包的时候肯定要指定抓什么包,什么包都抓的话,一会你的电脑内存就飙升好多(别问我为啥晓得,问就是 30g 内存都让它吃了)。

Wireshark 有个 抓包过滤器 显示过滤器 。抓包的时候指定抓什么包这是 抓包过滤器的作用 ,抓包之后显示显示那些内容那是 显示过滤器的作用

# -i 指定那个网卡 
# -f 指定抓包过滤器
# -Y 显示过滤器
# -w 指定抓包数据到文件,没有 -w 输入屏幕
# -V 显示 TCP/IP 每层包的详细信息,倡议将抓包的文件在图形化界面中查看,不指定 -V
tshark  -i en0 -f "tcp" -Y "http"

# 抓取拜访 www.mflyyou.cn 的包
tshark  -i en0 -w a.pcap -f "host www.mflyyou.cn"

# 指定抓那个协定 tcp,ip,icmp,arp,udp
tshark  -i en0 -f "tcp"


# host 指定域名或者 ip
# port 指定端口
# 拜访 www.mflyyou.cn 的包,或者 icmp. ping www.baidu.com 也会被抓到
tshark  -i en0 -f "host www.mflyyou.cn || icmp"
tshark  -i en0 -f "port 80"

# 条件之间反对逻辑运算符 || && !
# 抓取 ssh 链接的包
tshark  -i en0 -f "host www.mflyyou.cn && port 22"

参考资料

《图解 TCP/IP》

linux-tcp 阐明

鸟哥私房菜:根底网络的概念


本文由 张攀钦的博客 http://www.mflyyou.cn/ 创作。可自在转载、援用,但需署名作者且注明文章出处。

如转载至微信公众号,请在文末增加作者公众号二维码。微信公众号名称:Mflyyou

正文完
 0