LINUX 网络编程
1.网络协议
osi 参考模型7层和tcp/ip 模型4层: |
---|
TCP/IP 协议族的每一层的作用 | 数据链路层具体 | 网络层具体 | 数据封装和解封装过程 |
---|
标记(Flags) | 生存时间(TTL) | 协议(Protocol) | 头部校验(Header Checksum) |
---|
1.6.1. 路由器工作原理 | 1.6.2 路由和交换之间的主要区别 | 1.6.3. 以太网交换机工作原理 | 1.6.4. hub 工作原理 |
---|
|
|
|
|——
1.1. TCP/IP 协议概述
协议(protocol):通信双方必须遵循的规矩,由 iso 规定,rpc(远程过程调用,Remote Procedure Call,见下图)文档
osi 参考模型:
(应-表-会-传-网-数-物)
应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
tcp/ip 模型 4 层:
- 应用层:
http 超文本传输协议 | ftp 文件传输协议 | telnet 远程登录 |
---|---|---|
ssh 安全外壳协议 | smtp 简单邮件发送 | pop3 收邮件 |
- 传输层:
tcp 传输控制协议 | udp 用户数据包协议 |
---|
TCP 协议:传输控制协议,面向连接的协议,能保证传输安全可靠,速度慢(有 3 次握手)
UDP 协议:用户数据包协议,非面向连接,速度快,不可靠
- TCP:(传输控制协议) 为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并 适用于要求得到响应的应用程序。
- UDP:(用户数据包协议) 提供了无连接通信,且不对传送包进行可靠的保证。适合于一次传输 少量数据。
- 网络层
ip 网际互联协议 | icmp 网络控制消息协议(ping) | igmp 网络组管理协议 |
---|
- IP:(网际互联协议) 负责在主机和网络之间寻址和路由数据包。
- ICMP:(网络控制消息协议) 用于发送报告有关数据包的传送错误的协议。
- IGMP:(网络组管理协议) 被 IP 主机用来向本地多路广播路由器报告主机组成员的协议。主机与本地路由器之间使用 Internet 组管理协议(IGMP,Internet Group Management Protocol)来进行组播组成员信息的交互
- 网络接口层
arp 地址转换协议 | rarp 反向地址转换协议 | mpls 多协议标签交换 |
---|
arp 地址转换协议:IP地址 → mac地址
rarp 反向地址转换协议:mac地址 → IP地址
- ARP:地址转换协议,用于获得同一物理网络中的硬件主机地址。是设备通过自己知道的 IP 地址来获得自己不知道的物理地址的协议。
- RARP:反向地址转换协议(RARP:Reverse Address Resolution Protocol) 反向地址转换协议 (RARP)允许局域网的物理机器从网关服务器的 ARP 表或者缓存上请求其 IP 地址。网络管理员在局域网网关路由器里创建一个表以映射物理地址(MAC)和与其对应的 IP 地址。当设置一台新的机器时, 其 RARP 客户机程序需要向路由器上的 RARP 服务器请求相应的 IP 地址。假设在路由表中已经设置 了一个记录,RARP 服务器将会返回 IP 地址给机器,此机器就会存储起来以便日后使用。 RARP 可 以使用于以太网、光纤分布式数据接口及令牌环 LAN 。
通常是 ip 地址后面跟上端口号用来唯一确定通信的进程
ip 用来定位主机 port 区别应用(进程)
端口号:
http 的端口号→ 80 | ssh → 22 | telnet → 23 | ftp → 21 | 用户自己定义的通常要大于 1024 |
---|
1.2. OSI 参考模型及 TCP/IP 参考模型
TCP/IP 协议族的每一层的作用:
- 网络接口层:负责将二进制流转换为数据帧,并进行数据帧的发送和接收。要注意的是数据帧是 独立的网络信息传输单元。
- 网络层:负责将数据帧封装成 IP 数据报,并运行必要的路由算法。 ·
(路由算法,又名选路算法,可以根据多个特性来加以区分。算法的目的是找到一条从源路由器到目的路由器的具有最低费用的路径,路由算法是提高路由协议功能,尽量减少路由时所带来开销的算法) - 传输层:负责端对端之间的通信会话连接和建立。传输协议的选择根据数据传输方式而定。 ·
- 应用层:负责应用程序的网络访问,这里通过端口号来识别各个不同的进程。
数据链路层:
链路层有以太网、令牌环网等标准,链路层负责网卡设备的驱动、帧同步(即从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。
交换机是工作在链路层的网络设备,可以在不同的链路层网络之间转发数据帧(比如十兆以太网和百兆以太网之间、 以太网和令牌环网之间),由于不同链路层的帧格式不同,交换机要将进来的数据包拆掉链路层首部重 新封装之后再转发。
网络层:
网络层 的 IP 协议是构成 Internet 的基础。Internet 上的主机通过 IP 地址来标识,Internet上有大量路由器负责根据 IP 地址选择合适的路径转发数据包,数据包从 Internet 上的源主机到目的主机往往要经过十多个路由器。路由器是工作在第三层的网络设备,同时兼有交换机的功能,可以在不同的链路层接口之间转发数据包,因此路由器需要将进来的数据包拆掉网络层和链路层两层首部并重新封装。
(IP 协议不保证传输的可靠性,数据包在传输过程中可能丢失,可靠性可以在上层协议或应用程序中提供支持。 )
网络层负责点到点(ptop,point-to-point)的传输(这里的“点”指主机或路由器),而传输层负责端到端(etoe,end-to-end)的传输(这里的“端”指源主机和目的主机)。传输层可选择 TCP 或 UDP 协议。
- 点到点是物理拓扑,如光纤,就必须是点到点连接,DDN专线也是,即两头各一个机器中间不能有机器。
端到端是网络连接。网络要通信,必须建立连接,不管有多远,中间有多少机器,都必须在两头(源和目的)间建立连接,一旦连接建立起来,就说已经是端到端连接了,即端到端是逻辑链路,这条路可能经过了很复杂的物理路线,但两端主机不管,只认为是有两端的连接,而且一旦通信完成,这个连接就释放了,物理线路可能又被别的应用用来建立连接了。TCP就是用来建立这种端到端连接的一个具体协议,SPX也是。
(点到点和端到端的区别)
以太网驱动程序首先根据以太网首部中的“上层协议”字段确定该数据帧的有效载荷(payload,指除去协议首部之外实际传输的数据)是 IP、ARP 还是 RARP 协议的数据报,然后交给相应的协议处理。
假如是 IP 数据报,IP 协议再根据 IP 首部中的“上层协议”字段确定该数据报的有效载荷是 TCP、UDP、 ICMP 还是 IGMP,然后交给相应的协议处理。
假如是 TCP 段或 UDP 段,TCP 或 UDP 协议再根据 TCP 首部或 UDP 首部的“端口号”字段确定应该将应用层数据交给哪个用户进程。
IP 地址是标识网络中不同主机的地址,而端口号就是同一台主机上标识不同进程的地址,IP 地址和端口号合起来标识网络中唯一的进程。
虽然 IP、ARP 和 RARP 数据报都需要以太网驱动程序来封装成帧,但是从功能上划分,ARP 和 RARP 属于链路层,IP 属于网络层。虽然 ICMP、IGMP、TCP、UDP 的数据都需要 IP 协议来封装成数据报, 但是从功能上划分,ICMP、IGMP 与 IP 同属于网络层,TCP 和 UDP 属于传输层。
数据封装和解封装过程
1.3. 以太网帧格式
源地址和目的地址是指网卡的硬件地址(也叫 MAC 地址),长度是 48(6×4+6×4) 位,是在网卡出厂时固化的。可在 shell 中使用 ifconfig 命令查看,“HWaddr 00:15:F2:14:9E:3F”部分就是硬件地址。协议字段有三种值,分别对应 IP、ARP、RARP。帧尾是 CRC 校验码。
以太网帧中的数据长度规定最小 46 字节,最大 1500 字节,ARP 和 RARP 数据包的长度不够 46 字 节,要在后面补填充位。最大值 1500 称为以太网的最大传输单元(MTU),不同的网络类型有不同的 MTU,如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的 MTU,则需要对数据 包进行分片(fragmentation)。ifconfig 命令输出中也有“MTU:1500”。注意,MTU 这个概念指数据帧中有效载荷的最大长度,不包括帧头长度。
1.4. ARP 数据报格式
在网络通讯时,源主机的应用程序知道目的主机的 IP 地址和端口号,却不知道目的主机的硬件地址, 而数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃。因此在通讯前必须获得目的主机的硬件地址。ARP 协议就起到这个作用。源主机发出 ARP 请求,询问 “IP 地址是 192.168.0.1 的主机的硬件地址是多少”,并将这个请求广播到本地网段(以太网 帧首部的硬件地址填 FF:FF:FF:FF:FF:FF 表示广播),目的主机接收到广播的 ARP 请求,发现其中的 IP 地址与本机相符,则发送一个 ARP 应答数据包给源主机,将自己的硬件地址填写在应答包中。
每台主机都维护一个 ARP 缓存表,可以用 arp -a 命令查看。缓存表中的表项有过期时间(一般为 20 分钟),如果 20 分钟内没有再次使用某个表项,则该表项失效,下次还要发 ARP 请求来获得目的主机的硬件地址。
ARP 数据报的格式如下所示:
源 MAC 地址、目的 MAC 地址在以太网首部和 ARP 请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。
硬件类型指链路层网络类型,1 为以太网,协议类型指要转换的地址类型,0x0800 为 IP 地址,后面两个地址长度对于以太网地址和 IP 地址 分别为 6 和 4(字节),op 字段为 1 表示 ARP 请求,op 字段为 2 表示 ARP 应答。
看一个具体的例子。
请求帧如下(为了清晰在每行的前面加了字节计数,每行 16 个字节):
由于以太网规定最小数据长度为 46 字节,ARP 帧长度只有 28 字节,因此有 18 字节填充位。
应答帧如下:
1.5. IP 数据包格式
版本号(Version):长度 4 比特。标识目前采用的 IP 协议的版本号。一般的值为 0100(IPv4),0110 (IPv6)
IP 包头长度(Header Length):长度 4 比特。这个字段的作用是为了描述 IP 包头的长度,因为在 IP 包头中有变长的可选部分。该部分占 4 个 bit 位,单位为 32bit(4 个字节),即本区域值 = IP 头部长度 (单位为 bit)/(8×4),因此,一个 IP 包头的长度最长为“1111”,即 15*4=60 个字节。IP 包头最小长度为 20 字节。
服务类型(Type of Service):长度 8 比特。8 位 按位被如下定义 PPP DTRC0
- PPP:定义包的优先级,取值越大数据越重要
000 普通 (Routine)
001 优先的 (Priority)
010 立即的发送 (Immediate)
011 闪电式的 (Flash)
100 比闪电还闪电式的 (Flash Override)
101 CRI/TIC/ECP(找不到这个词的翻译)
110 网间控制 (Internetwork Control)
111 网络控制 (Network Control)
D 时延: 0:普通 1:延迟尽量小
T 吞吐量: 0:普通 1:流量尽量大
R 可靠性: 0:普通 1:可靠性尽量大
M 传输成本: 0:普通 1:成本尽量小
0 最后一位被保留,恒定为 0
IP 包总长(Total Length):长度 16 比特。 以字节为单位计算的 IP 包的长度 (包括头部和数据),所以 IP 包最大长度 65535 字节。
标识符(Identifier):长度 16 比特。该字段和 Flags 和 Fragment Offest 字段联合使用,对较大的上层数据包进行分段(fragment)操作。路由器将一个包拆分后,所有拆分开的小包被标记相同的值,以便目 的端设备能够区分哪个包属于被拆分开的包的一部分。
标记(Flags):长度 3 比特。该字段第一位不使用。第二位 是 DF(Don’t Fragment)位,DF 位设为 1 时表明路由器不能对该上层数据包分段。如果一个上层数据包无法在不分段的情况下进行转发,则路由器会丢弃该上层数据包并返回一个错误信息。第三位 是 MF(More Fragments) 位,当路由器对一个上层数据包分段,则路由器会在除了最后一个分段的 IP 包的包头中将 MF 位设为 1。 (为1时 后面还有,为0,最后一个)
片偏移(Fragment Offset):长度 13 比特。表示该 IP 包在该组分片包中位置,接收端靠此来组装还原 IP 包。
生存时间(TTL):长度 8 比特。当 IP 包进行传送时,先会对 该字段赋予某个特定的值。当 IP 包经过每一个沿途的路由器的时候,每个沿途的路由器会将 IP 包的 TTL 值减少 1。如果 TTL 减少为 0,则该 IP 包会被丢弃。这个字段可以防止由于路由环路而导致 IP 包在网络中不停被转发。
- TTL 的作用是限制 IP 数据包在计算机网络中的存在的时间。TTL 的最大值是 255,TTL 的一个推荐值是 64。
- 虽然 TTL 从字面上翻译,是可以存活的时间,但 实际上 TTL 是 IP 数据包在计算机网络中可以转发的最大跳数。
- TTL 字段由 IP 数据包的发送者设置,在 IP 数据包从源到目的的整个转发路径上,每经过一个路由器,路由器都会修改这个 TTL 字段值,具体的做法是把该 TTL 的值减 1,然后再将 IP 包转发出去。
- 如果在 IP 包到达目的 IP 之前,TTL 减少为 0,路由器将会丢弃收到的 TTL=0 的 IP 包并向 IP 包 的发送者发送 ICMP time exceeded 消息。
(TTL 的主要作用是避免 IP 包在网络中的无限循环和收发,节省了网络资源,并能使 IP 包的发送者能收到告警消息。 ) - TTL 是由发送主机设置的,以防止数据包不断在 IP 互联网络上永不终止地循环。转发 IP 数据包时,要求路由器至少将 TTL 减小 1。
协议(Protocol):长度 8 比特。标识了上层所使用的协议。 以下是比较常用的协议号:
1 ICMP
2 IGMP
6 TCP
17 UDP
88 IGRP
89 OSPF
头部校验(Header Checksum):长度 16 位。用来做 IP 头部的正确性检测,但不包含数据部分。 因为每个路由器要改变 TTL 的值,所以路由器会为每个通过的数据包重新计算这个值。
起源和目标地址(Source and Destination Addresses):这两个地段都是 32 比特。标识了这个 IP 包的起 源和目标地址。要注意除非使用 NAT,否则整个传输的过程中,这两个地址不会改变。
IP 包头基本的 20 字节完毕,此后部分属于可选项,不是必须的部分。
可选项(Options):这是一个可变长的字段。该字段属于可选项,主要用于测试,由起源设备根据需要改写。可选项目包含以下内容:
松散源路由(Loose source routing):给出一连串路由器接口的 IP 地址。IP 包必须沿着这些 IP 地址传送,但是允许在相继的两个 IP 地址之间跳过多个路由器。
严格源路由(Strict source routing):给出一连串路由器接口的 IP 地址。IP 包必须沿着这些 IP 地址传送,如果下一跳不在 IP 地址表中则表示发生错误。
路由记录(Record route):当 IP 包离开每个路由器的时候记录路由器的出站接口的 IP 地址。
时间戳(Timestamps):当 IP 包离开每个路由器的时候记录时间。
填充(Padding):因为 IP 包头长度(Header Length)部分的单位为 32bit,所以 IP 包头的长度必须为 32bit 的整数倍。因此,在可选项后面,IP 协议会填充若干个 0,以达到 32bit 的整数倍
1.6. 路由(route)
路由(名词) :数据包从源地址到目的地址所经过的路径,由一系列路由节点组成。
路由(动词) :某个路由节点为数据包选择投递方向的选路过程。
1.6.1. 路由器工作原理
路由器(Router)是连接因特网中各局域网、广域网的设备,它会根据信道的情况自动选择和设定路由,以最佳路径,按前后顺序发送信号的设备。
传统地,路由器工作于 OSI 七层协议中的第三层,其主要任务是接收来自一个网络接口的数据包, 根据其中所含的目的地址,决定转发到下一个目的地址。
首先得在转发路由表中查找它的目的地址,若找到了目的地址,就在数据包的帧格前添加下一个MAC地址,同时IP数据包头的TTL(Time To Live)域也开始减数, 并重新计算校验和。当数据包被送到输出端口时,它需要按顺序等待,以便被传送到输出链路上。
路由器在工作时能够按照某种路由通信协议查找设备中的路由表。如果到某一特定节点有一条以上的路径,则基本预先确定的路由准则是选择最优(或最经济)的传输路径。 由于各种网络段和其相互连 接情况可能会因环境变化而变化,因此路由情况的信息一般也按所使用的路由信息协议的规定而定时更新。
网络中,每个路由器的基本功能都是按照一定的规则来动态地更新它所保持的路由表,以便保持路由信息的有效性。为了便于在网络间传送报文,路由器总是先按照预定的规则把较大的数据分解成适当大小的数据包,再将这些数据包分别通过相同或不同路径发送出去。当这些数据包按先后秩序到达目的 地后,再把分解的数据包按照一定顺序包装成原有的报文形式。路由器的分层寻址功能是路由器的重要 功能之一,该功能可以帮助具有很多节点站的网络来存储寻址信息,同时还能在网络间截获发送到远地 网段的报文,起转发作用;选择最合理的路由,引导通信也是路由器基本功能;多协议路由器还可以连 接使用不同通信协议的网络段,成为不同通信协议网络段之间的通信平台。
1.6.2. 路由和交换之间的主要区别
交换发生在 OSI 参考模型第二层(数据链路层),而路由发生在第三层,即网络层。这一区别决定了路由和交换在移动信息的过程 中需使用不同的控制信息,所以两者 实现各自功能的方式是不同的。
1.6.3. 以太网交换机工作原理
以太网交换机是基于以太网传输数据的交换机,以太网采用共享总线型传输媒体方式的局域网。以太网交换机的结构是每个端口都直接与主机相连,并且一般都工作在全双工方式。交换机能同时连通许多对端口,使每一对相互通信的主机都能像独占通信媒体那样,进行无冲突地传输数据。
以太网交换机工作于 OSI 网络参考模型的第二层(即数据链路层),是一种基于 MAC(Media Access Control,介质访问控制)地址识别、完成以太网数据帧转发的网络设备。
1.6.4. hub 工作原理
集线器实际上就是中继器的一种,其区别仅在于集线器能够提供更多的端口服务,所以集线器又叫多口中继器。
集线器功能是随机选出某一端口的设备,并让它独占全部带宽,与集线器的上联设备(交换机、路 由器或服务器等)进行通信。从 Hub 的工作方式可以看出,它在网络中只起到信号放大和重发作用,其 目的是扩大网络的传输范围,而不具备信号的定向传送能力,是—个标准的共享式设备。其次是 Hub 只 与它的上联设备(如上层 Hub、交换机或服务器)进行通信,同层的各端口之间不会直接进行通信,而是 通过上联设备再将信息广播到所有端口上。 由此可见,即使是在同一 Hub 的不同两个端口之间进行通 信,都必须要经过两步操作:
第一步是将信息上传到上联设备;
第二步是上联设备再将该信息广播到所有端口上。
Hub 功能非常弱,目前已经几乎消失殆尽(都购买不着),现在都是 4 口交换机,8 口交换机,或者是无线路由器。
1.7. ICMP 协议
ICMP 是(Internet Control Message Protocol)Internet 控制报文协议。它是 TCP/IP 协议族的一个子协议,主要用于在主机、路由器之间传递控制消息,包括报告错误、交换受限控制和状态信息等。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。当遇到 IP 数据无法访问目标、IP 路由器无法按当前的传输速率转发数据包等情况时,会自动发送 ICMP 消息。ICMP 报文在 IP 帧结构的首部协议类型字段 (Protocol 8bit) 的值 = 1。
TICMP 协议是一种面向无连接的协议,用于传输出错报告控制信息。它是一个非常重要的协议,它对于网络安全具有极其重要的意义。
如下图所示,ICMP 包有一个 8 字节长的包头,其中前 4 个字节是固定的格式,包含 8 位类型字段, 8 位代码字段和 16 位的校验和;后 4 个字节根据 ICMP 包的类型而取不同的值。
ICMP 提供一致易懂的出错报告信息。发送的出错报文返回到发送原数据的设备,因为只有发送设备才是出错报文的逻辑接受者。发送设备随后可根据 ICMP 报文确定发生错误的类型,并确定如何才能更好地重发失败的数据包。但是 ICMP 唯一的功能是报告问题而不是纠正错误,纠正错误的任务由发送方完成。
我们在网络中经常会使用到 ICMP 协议,比如我们经常使用的用于检查网络通不通的 Ping 命令 (Linux 和 Windows 中均有),这个**“Ping”的过程实际上就是 ICMP 协议工作的过程**。还有其他的网络命令如跟踪路由的 Tracert 命令也是基于 ICMP 协议的。
TYPE | CODE | Description | Query | Error |
---|---|---|---|---|
0 | 0 | Echo Reply——回显应答(Ping 应答) | x | |
3 | 0 | Network Unreachable——网络不可达 | x | |
3 | 1 | Host Unreachable——主机不可达 | x | |
3 | 2 | Protocol Unreachable——协议不可达 | x | |
3 | 3 | Port Unreachable——端口不可达 | x | |
3 | 4 | Fragmentation needed but no frag. bit set——需要进行分片但设置不分片比特 | x | |
3 | 5 | Source routing failed——源站选路失败 | x | |
3 | 6 | Destination network unknown——目的网络未知 | x | |
3 | 7 | Destination host unknown——目的主机未知 | x | |
3 | 8 | Source host isolated (obsolete)——源主机被隔离(作废不用) | x | |
3 | 9 | Destination network administratively prohibited——目的网络被强制禁止 | x | |
3 | 10 | Destination host administratively prohibited——目的主机被强制禁止 | x | |
3 | 11 | Network unreachable for TOS——由于服务类型 TOS,网络不可达 | x | |
3 | 12 | Host unreachable for TOS——由于服务类型 TOS,主机不可达 | x | |
3 | 13 | Communication administratively prohibited by filtering——由于过滤,通信被强制禁止 | x | |
3 | 14 | Host precedence violation——主机越权 | x | |
3 | 15 | Precedence cutoff in effect——优先中止生效 | x | |
4 | 0 | Source quench——源端被关闭(基本流控制) | ||
5 | 0 | Redirect for network——对网络重定向 | ||
5 | 1 | Redirect for host——对主机重定向 | ||
5 | 2 | Redirect for TOS and network——对服务类型和网络重定向 | ||
5 | 3 | Redirect for TOS and host——对服务类型和主机重定向 | ||
8 | 0 | Echo request——回显请求(Ping 请求) | x | |
9 | 0 | Router advertisement——路由器通告 | ||
10 | 0 | Route solicitation——路由器请求 | ||
11 | 0 | TTL equals 0 during transit——传输期间生存时间为 0 | x | |
11 | 1 | TTL equals 0 during reassembly——在数据报组装期间生存时间为 0 | x | |
12 | 0 | IP header bad (catchall error)——坏的 IP 首部(包括各种差错) | x | |
12 | 1 | Required options missing——缺少必需的选项 | x | |
13 | 0 | Timestamp request (obsolete)——时间戳请求(作废不用) | x | |
14 | Timestamp reply (obsolete)——时间戳应答(作废不用) | x | ||
15 | 0 | Information request (obsolete)——信息请求(作废不用) | x | |
16 | 0 | nformation reply (obsolete)——信息应答(作废不用) | x | |
17 | 0 | Address mask request——地址掩码请求 | x | |
18 | 0 | Address mask reply——地址掩码应答 |
1.8. TCP 协议
1.8.1. 概述
TCP 是 TCP/IP 体系中面向连接的运输层协议,它提供全双工和可靠交付的服务。它采用许多机制来确保端到端结点之间的可靠数据传输,如采用序列号、确认重传、滑动窗口等。
- TCP 要为所发送的每一个报文段加上序列号,保证每一个报文段能被接收方接收,并只被正确的接收一次。
- TCP 采用具有重传功能的积极确认技术作为可靠数据流传输服务的基础。这里“确认”是指接收端在正确收到报文段之后向发送端回送一个确认(ACK)信息。发送方将每个已发送的报文段备份在自己的缓冲区里,而且在收到相应的确认之前是不会丢弃所保存的报文段的。“积极”是指发送发在每一个报文段发送完毕的同时启动一个定时器,加入定时器的定时期满而关于报文段的确认信息还没有达到,则发送方认为该报文段已经丢失并主动重发。为了避免由于网络延时引起迟到的确认和重复的确认,TCP 规定在确认信息中捎带一个报文段的序号(seq),使接收方能正确的将报文段与确认联系起来。
- 采用可变长的滑动窗口协议进行流量控制,以防止由于发送端与接收端之间的不匹配而引起的数据丢失。这里所采用的滑动窗口协议与数据链路层的滑动窗口协议在工作原理上完全相同,唯一的区别在于滑动窗口协议用于传输层是为了在端对端节点之间实现流量控制,而用于数据链路层是为了在 相邻节点之间实现流量控制。TCP 采用可变长的滑动窗口,使得发送端与接收端可根据自己的 CPU 和 数据缓存资源对数据发送和接收能力来进行动态调整,从而灵活性更强,也更合理.。
一次完整的TCP通信:建立连接(三次握手),数据传输,断开连接(四次挥手)
1.8.2. TCP 报文头部格式
序列号 seq: 16位的二进制数,每个TCP报文都有,确保有序接收。
确认号 ack :16位的二进制数,每个TCP报文都有,向对方确认收到了多少数据,同时也表示期望的对方(接收方)的下一次发送的报文的sequence number是多少。
SYN同步标志位:代表是建立连接的请求报文,同步序列编号只有第一次和第二次握手时为1。 同步双发的初始序列号
ACK确认标志位:向对端确认收到的报文序号时为1。 FIN结束标志位:四次挥手时第一次和第三次挥手时为1,代表通知对方断开。
窗口大小:滑动窗口的大小,滑动窗口用于流量控制。
- 源端口、目的端口:16 位长。标识出远端和本地的端口号。
- 序号:32 位长。标识发送的数据报的顺序。 ·确认号:32 位长。希望收到的下一个数据报的序列号。
- TCP 头长:4 位长。表明 TCP 头中包含多少个 32 位字。就是有多少个 4 个字节
- 4 位未用。
CWR: 拥塞窗口减(发送方降低它的发送速率)
ECE: ECN 回显(发送方收到了一个更早的拥塞报告)
URG:紧急指针(urgent pointer)有效,紧急指针指出在本报文段中的紧急数据的最后一个字节的序号
ACK:ACK 位置 1 表明确认号是合法的。如果 ACK 为 0,那么数据报不包含确认信息,确认字段被 省略。 - PSH:表示是带有 PUSH 标志的数据。接收方因此请求数据报一到便可送往应用程序而不必等到缓冲区装满时才发送。当 PSH=1 时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略
- RST:用于复位由于主机崩溃或其他原因而出现的错误的连接。还可以用于拒绝非法的数据报或拒绝 连接请求。当 RST 为 1 时,表明 TCP 连接中出现了严重的差错,必须释放连接,然后再重新建立连接。
- SYN:用于建立连接。当 SYN=1 时,表示发起一个连接请求。
- FIN:用于释放连接。当 FIN=1 时,表明此报文段的发送端的数据已发送完成,并要求释放连接。
- 窗口大小:16 位长。窗口大小字段表示在确认了字节之后还可以发送多少个字节。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。
- 校验和:16 位长。是为了确保高可靠性而设置的。它校验头部、数据和伪 TCP 头部之和。
- 可选项:0 个或多个 32 位字。包括最大 TCP 载荷,窗口比例、选择重复数据报等选项。
- 大小:从源端口到紧急指针,总计 20 个字节,没有任何选项字段的 TCP 头部长度为 20 字节;最多可以有 60 字节的 TCP 头部(注:IP 地址在 IP 包头部)
1.8.3. TCP 的三次握手
在利用 TCP 实现源主机和目的主机通信时,目的主机必须同意,否则 TCP 连接无法建立。为了确保 TCP 连接的成功建立,TCP 采用了一种称为三次握手的方式,三次握手方式使得“序号/确认号”系 统能够正常工作,从而使它们的序号达成同步。如果三次握手成功,则连接建立成功,可以开始传送数据信息。
三次握手:为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用程序。
其三次握手分别为:
- 源主机 A 的 TCP 向主机 B 发送连接请求报文段,其首部中的 SYN(同步)标志位应置为 1,表示想跟目标主机 B 建立连接,进行通信,并发送一个同步序列号 X(例:SEQ=100)进行同步,表明在 后面传送数据时的第一个数据字节的序号为 X+1(即101)。
- 目标主机 B 的 TCP 收到连接请求报文段后,如同意,则发回确认。再确认报中应将 ACK 位和 SYN 位置为 1.确认号为
X+1,同时也为自己选择一个序号 Y。 - 源主机 A 的 TCP 收到目标主机 B 的确认后要想目标主机 B 给出确认。其 ACK 置为 1,确认号 为 Y+1,而自己的序号为
X+1。TCP 的标准规定,SYN 置 1 的报文段要消耗掉一个序号。(A收到B的ACK,是不会对ACK再做确认的 )
运行客户进程的源主机 A 的 TCP 通知上层应用进程,连接已经建立。当源主机 A 向目标主机 B 发送第一个数据报文段时,其序号仍为 X+1,因为前一个确认报文段并不消耗序号。
当运行服务进程的目标主机 B 的 TCP 收到源主机 A 的确认后,也通知其上层应用进程,连接已经建立。至此建立了一个全双工的连接
面试题考点:
1. 为什么需要三次握手? (常见面试题)
理解1:“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。(不能使用两次握手的原因)。
- 假设不采用“三次握手”(“两次握手就能成功”),那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。
理解2:请求方发送同步信号,接收方收到后需要确认,TCP确认收到的包
- ① 发送同步信号 SYN+A 的初始序列号 seq=x
(可以认为是A发B收的请求 ) - ② B 确认收到 A 的同步信号,发送ACK=1,ack=x+1
- ③ B发送同步信号 SYN + B 的初始化序列号 seq=y
(可以认为是B发A收的请求 ) - ④ A确认收到B的同步信号,发送 ACK=1,ack=y+1
- 为了减少时延,避免资源的浪费,② 和 ③ 两步合并发送
理解3:其实所谓的TCP三次握手请求连接,无非就是初始化一个序列号,保证后面的数据有序到达。
(前两次握手成功后(两次SYN),双方就已经确认了对方的序列号。这样双方都知道什么样的
序列号是合法的,什么样的是不合法的。server端接收到不合法的就丢弃,接收到合法的就 认为连接是建立成功的。)
2. 握手时包丢了怎么办?
第一个包,即A发给B的SYN 中途被丢,没有到达B A会周期性超时重传,直到收到B的确认
第二个包,即B发给A的SYN +ACK 中途被丢,没有到达A B会周期性超时重传,直到收到A的确认
第三个包,即A发给B的ACK 中途被丢,没有到达B
- A发完ACK,单方面认为TCP为 Established状态,而B显然认为TCP为 Active(SYN_REVD)状态
- A会超时重传这个ACK吗?不会!TCP不会为没有数据的ACK超时重传
- 1.双方都没有数据发送,B会周期性超时重传,直到收到A的确认,收到之后B的 TCP 连接也为 Established状态,双向可以发包
- 2.假定此时A有数据发送,B收到A的 Data + ACK,自然会切换为Established(已确认)状态,并接受A的Data A发给B的第三次握手的seq=x+1
(A下一次发给B的正常数据的seq也是x+1 ) - 3.假定B有数据发送,数据发送不了,会一直周期性超时重传SYN + ACK,直到收 到A的确认才可以发送数据
1.8.4. TCP 的四次挥手
由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的连接。收到一个 FIN 只意味着这一方向上没有数据流动,一 个 TCP 连接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
其四次挥手分别为:
- TCP 客户端发送一个 FIN,用来关闭客户到服务器的数据传送。
- 服务器收到这个 FIN,它发回一个 ACK,确认序号为收到的序号加 1。和 SYN 一样,一个 FIN 将占用一个序号。
- 服务器关闭客户端的连接,发送一个 FIN 给客户端。
- 客户端发回 ACK 报文确认,并将确认序号设置为收到序号加 1。
TCP 状态:
-
CLOSED: 表示初始状态。
-
LISTEN: 表示服务器端的某个 SOCKET 处于监听状态,可以接受连接了。
-
SYN_RCVD: 这个状态表示接受到了 SYN 报文,在正常情况下,这个状态是服务器端的 SOCKET 在建立 TCP 连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用 netstat 你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。因此这种状态时,当收到客户端的 ACK 报文后,它会进入到 ESTABLISHED 状态。
-
SYN_SENT: 这个状态与 SYN_RCVD 遥想呼应,当客户端 SOCKET 执行 CONNECT 连接时,它首先发送 SYN 报文,因此也随即它会进入到了 SYN_SENT 状态,并等待服务端的发送三次握手中的第 2 个报文。 SYN_SENT状态表示客户端已发送 SYN 报文。
-
ESTABLISHED: 表示连接已经建立了。
-
FIN_WAIT_1: 其实 FIN_WAIT_1 和 FIN_WAIT_2 状态的真正含义都是表示等待对方的 FIN 报文。
而这两种状态的区别是:
( FIN_WAIT_1 状态实际上是当 SOCKET 在 ESTABLISHED 状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 SOCKET 即进入到 FIN_WAIT_1 状态。)
( 而当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态)
( 当然在实际的正常情况下,无论对方何种情况下,都应该马上回应 ACK 报文,所以 FIN_WAIT_1 状态一般是比较难见到的,而 FIN_WAIT_2 状态还有时常常 可以用 netstat 看到。) -
FIN_WAIT_2: 上面已经详细解释了这种状态,实际上 FIN_WAIT_2 状态下的 SOCKET,表示半连接,也即有一方要求 close 连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
-
TIME_WAIT : 表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回到 CLOSED 可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。
-
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送 FIN 报文后,按理来说是应该先收到(或同时收到)对方的 ACK 报文,再收到对方的 FIN 报文。但是 CLOSING 状态表示你发送 FIN 报文后,并没有收到对方的 ACK 报文,反而却也收到了对方的 FIN 报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时 close 一个 SOCKET 的话,那么就出现了双方同时发送 FIN 报文的情况,也就会出现 CLOSING 状态,表示 双方都正在关闭 SOCKET 连接。
-
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方 close 一个 SOCKET 后发送 FIN 报文给自己,你系统毫无疑问地会回应一个 ACK 报文给对方,此时则进入到 CLOSE_WAIT 状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close 这个 SOCKET,发送 FIN 报文给对方,也即关闭连接。所以你在 CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。
-
LAST_ACK: 这个状态是被动关闭一方在发送 FIN 报文后,最后等待对方的 ACK 报文。 当收到 ACK 报文后,也即可以进入到 CLOSED 可用状态了。
面试题考点:
- 半关闭
- 在 TIME_WAIT 状态时两端的端口不能使用,要等到 2MSL 时间结束才可继续使用。当连接处于2MSL 等待阶段时任何迟到的报文段都将被丢弃
- 2MSL(Maximum Segment Lifetime),中文可以译为“最大报文段生存时间”, 他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
问题1:为什么建立连接只需要三次握手?断开连接需要四次挥手?
- 因为 TCP 是全双工模式,接收到 FIN 时意味将没有数据再发来,但是还是可以继续发送数据。
当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当 Server 端收到FIN报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,“你发的 FIN 报文我收到了”。只有等到我 Server 端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
问题2:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回CLOSED状态?
- 1. 保证TCP协议的全双工连接能够可靠关闭
如果Client直接 CLOSED了,那么由于 IP 协议的不可靠性或者是其它网络原因,导致 Server 没有收到 Client 最后回复的 ACK 。那么 Server 就会在超时之后继续发送FIN,此时由于 Client 已经 CLOSED了,就找不到与重发的 FIN 对应的连接,最后 Server 就会收到 RST 而不是ACK, Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client 不是直接进入CLOSED,而是要保持 TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。 - 2. 保证这次连接的重复数据段从网络中消失
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假设网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的 ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到 ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该 ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待 2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。MSL 指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连 接。 A发给B的第四次回收丢了,B发送第三次挥手之后的超时重传的计时器的时间加上数据包在网络中的传输时间一定小于2MSL的,所以能够保证第四次挥手的包丢了,仍然有足够的时间超时重传。
1.8.5. MTU 与 MSS
MTU: Maxitum Transmission Unit 最大传输单元,由硬件规定,如以太网的MTU为1500字
节
MSS: Maxitum Segment Size 最大分段大小,为TCP数据包每次传输的最大数据分段大小,一般由发送端向对端TCP通知对端在每个分节中能发送的最大TCP数据。
(MSS值为MTU值减去IPv4 Header(20 Byte)和TCP header(20 Byte)得到。)
MTU 是网络传输最大报文包,MSS 是网络传输数据最大值。
具体分析如下:
-
MSS 加包头数据就等于 MTU。
(简单说拿 TCP 包做例子。 报文传输 1400 字节的数据的话,那么 MSS 就是 1400,再加上 20 字节 IP 包头,20 字节 tcp 包头,那么 MTU 就是 1400+20+20)
(当然传输的时候其他的协议还要加些包头在前面,总之 MTU 就是总的最后发出去的报文大小。MSS 就是你需要发出去的数据大小。) -
为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes) 所以往往 MSS 为 1460。 通讯双方会根据双方提供的 MSS 值得最小值确定为这次连接的最大 MSS 值。
思考:TCP 三次握手时下列哪种情况未发生?
A. 确认序列号 B. MSS C. 滑动窗口大小 D. 拥塞控制大小
(D未发生)
更多的关于TCP的拥塞控制
1.9. UDP 协议
(无连接,不可靠。效率高,实时性好。)
(1)概述 :
UDP 即用户数据报协议,它是一种无连接协议,因此不需要像 TCP 那样通过三次握手来建立一个连接。同时,一个 UDP 应用可同时作为应用的客户或服务器方。由于 UDP 协议并不需要建立一个明确的连接,因此建立 UDP 应用要比建立 TCP 应用简单得多。 它比 TCP 协议更为高效,也能更好地解决实时性的问题。
如今,包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都使用 UDP 协议。 使用 UDP 协议包括:TFTP、SNMP、NFS、DNS、BOOTP
(2)Udp 数据包头格式
报头由四个 16 位长(2 字节)字段组成,分别说明该报文的源端口、目的端口、报文长度以及校验值源、目标端口号字段:占 16 比特。作用与 TCP 数据段中的端口号字段相同,用来标识源端和目标端的应用进程。
- 长度字段:占 16 比特。标明 UDP 头部和 UDP 数据的总长度字节。数据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分(又称为数据负载)。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为 65535 字节。不过,一些实际应用往往会限制数据报的大小,有时会降低到 8192 字节
- 校验和字段:占 16 比特。用来对 UDP 头部和 UDP 数据进行校验。和 TCP 不同的是,对 UDP 来说, 此字段是可选项,而 TCP 数据段中的校验和字段是必须有的