赞
踩
独立模式:计算机之间相互独立。
网络互连:将多台计算机连接在一起,完成数据共享,数据共享本质是网络数据传输,即计算机之间通过网络来传输数据,也称为网络通信。
局域网,即 Local Area Network,简称LAN。Local 即标识了局域网是本地,局部组建的一种私有网络。局域网内的主机之间能方便的进行网络通信,又称为内网;局域网和局域网之间在没有连接的情况下,是无法通信的。
通过路由器,将多个局域网连接起来,在物理上组成很大范围的网络,就形成了广域网。广域网内部的局域网都属于其子网。
如果属于全球化的公共型广域网,则称为互联网(又称公网,外网),属于广域网的一个子集。有时在不严格的环境下说的广域网,其实是指互联网。
IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址,是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
用于定位主机(如网络主机、路由器等其他网络设备)的网络地址,描述的是路途总体的起点和终点,是给人使用的网络逻辑地址。
- 网络号:
标识网段,保证互相连接的两个网段(局域网)具有不同的标识。- 主机号:
标识主机,同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。
IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节如:01100100.00000100.00000101.00000110。),通常用“点分十进制”的方式来表示,即 a.b.c.d 的形式(a,b,c,d都是0~255之间的十进制整数),如:100.4.5.6。
A
B
C
D
E
特殊IP:127.*的IP地址用于本机环回测试(loop back),通常是127.0.0.1。
- 格式
- 作用
- 计算方式
- IPv4
IPv4数量=2^32,大约43亿左右,而TCP/IP协议规定,每个主机都需要有一个IP地址。对于全世界计算机来说,这个数量是不够的,且可以使用其他技术(动态IP)来解决IP地址不足的问题。- IPv6
长度128位,是IPv4的4倍,但因为目前IPv4还广泛的使用,所以IPv6也就没有普及。
端口号用于定位主机中的进程,在网络通信中进程可以通过绑定一个端口号来发送及接收网络数据。两个不同的进程,不能绑定同一个端口号,但一个进程可以绑定多个端口号(进程绑定一个端口号后,fork一个子进程,可以实现多个进程绑定一个端口号)。
端口号是0~65535范围的数字。
- 知名协议默认端口号:0 ~ 1023。
22端口:预留给SSH服务器绑定SSH协议
21端口:预留给FTP服务器绑定FTP协议
23端口:预留给Telnet服务器绑定Telnet协议
80端口:预留给HTTP服务器绑定HTTP协议
443端口:预留给HTTPS服务器绑定HTTPS协议
- 其他端口号:1023~65535。
0 ~ 1023 范围的知名端口号用于绑定知名协议,但某个服务器也可以使用其他 1024 ~ 65535 范围内的端口来绑定知名协议。
协议,网络协议的简称,网络协议是网络通信(网络数据传输)经过的所有网络设备都必须共同遵从的一组约定、规则。如怎么样建立连接、怎么样互相识别等。协议最终体现为在网络上传输的数据包的格式。
- 计算机之间的传输媒介是光信号和电信号,通过 “频率” 和 “强弱” 来表示 0 和 1 这样的信息。网络通信传输的数据类型可能有多种:图片,视频,文本等,基于网络传递各种不同的信息,需要使用协议来规定双方的数据式。
- 计算机生产厂商、计算机操作系统、计算机网络硬件设备有很多种,为了让这些不同厂商之间生产的计算机能够相互顺畅的通信就需要约定一个共同的标准,大家都来遵守。
- 语法:数据与控制信息的结构或格式
- 语义:需要发出何种控制信息,完成何种动作以及做出何种响应。语义主要用来说明通信双方应当怎么做。用于协调与差错处理的控制信息。
- 时序:事件实现顺序的详细说明。时序定义了何时进行通信,先讲什么,后讲什么,讲话的速度等。
- 源IP:标识源主机
- 源端口号:标识源主机中该次通信发送数据的进程
- 目的IP:标识目的主机
- 目的端口号:标识目的主机中该次通信接收数据的进程
- 协议号:标识发送进程和接收进程双方约定的数据格式
五元组在网络通信中的作用,类似于发送快递:
可以在cmd中,输入 netstat -ano 查看网络数据传输中的五元组信息。
Open System Interconnection,开放系统互连,是一个逻辑上的定义和规范,把网络从逻辑上分为了7层。OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输。
OSI 七层模型最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整。通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯。
- OSI 七层模型既复杂又不实用,没有落地实现,实际组建网络时以 OSI 七层模型中的部分网络分层来实现,分别是应用层、传输层、网络层、数据链路层(还有物理层)。在这几个网络分层的分层协议构成一组协议,取传输层的TCP/UDP协议和网络层的IP协议来命名这一组协议,即TCP/IP协议,这一组协议构成了TCP/IP协议簇,同时将这几个网络分层构成的模型称为TCP/IP 五层(或四层)模型。
- 应用层:负责应用程序间沟通。
如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。网络编程主要就是针对应用层。- 传输层:负责两台主机之间的数据传输。
如传输控制协议 (TCP),能够确保数据可靠的从源主机发送到目标主机。- 网络层:负责地址管理和路由选择。
例如在IP协议中,通过IP地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由)。路由器(Router)工作在网路层。- 数据链路层:负责设备之间的数据帧的传送和识别。两个设备(同一种数据链路节点)之间进行传递数据。
例如网卡设备的驱动、帧同步(就是说从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。有以太网、令牌环网,无线LAN等标准。交换机(Switch)工作在数据链路层。- 物理层(属于硬件层面,一般不过多讨论):负责光/电信号的传递方式。
比如现在以太网通用的网线(双绞线)、早期以太网采用的的同轴电缆(现在主要用于有线电视)、光纤,现在的wifi无线网使用电磁波等都属
于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等。集线器(Hub)工作在物理层。
- 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容,即TCP/IP五层模型的下四层。
- 对于一台路由器,它实现了从网络层到物理层,也即是TCP/IP五层模型的下三层。
对于一台交换机,它实现了从数据链路层到物理层,也即是TCP/IP五层模型的下两层。- 对于集线器,它只实现了物理层。
随着现在网络设备技术的不断发展,也出现了很多3层或4层交换机,这里说的是传统意义上的交换机和路由器,也称为二层交换机(工作在TCP/IP五层模型的下两层)、三层路由器(工作在TCP/IP五层模型的下三层)。
TCP/IP通讯协议在运作中采用了5层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
协议分层类似于打电话时,定义不同的层次的协议:
协议定义了两层间的接口规范。
分层最大的好处,类似于面向接口编程:协议定义好两层间的接口规范,接口实现了这个规范,让双方通过接口来完成对接。
对于使用方来说,并不关心提供方是如何实现的,只需要使用接口即可
对于提供方来说,利用封装的特性,隐藏了实现的细节,只需要开放接口即可。
应用层协议、传输层协议、网络层协议、数据链路层协议,(物理层协议)。
- 什么是DNS?
DNS,即Domain Name System,域名系统。DNS是一整套从域名映射到IP的系统。DNS协议是应用层协议,基于传输层UDP或TCP协议来实现。 TCP/IP中使用IP地址来确定网络上的一台主机,但是IP地址不方便记忆,且不能表达地址组织信息,于是人们发明了域名,并通过DNS来映射域名和IP址,每一个域名都对应着一个或n个IP地址。- DNS的工作原理:DNS服务器+hosts文件
网络通信发送数据时,如果使用目的主机的域名,需要先通过域名解析查找到对应的IP地址,域名解析使用DNS协议来传输数据。
域名解析的过程,可以简单的理解为发送端主机作为域名系统树形结构的一个子节点,通过域名信息,从下到上查找对应IP地址的过程。如果到根节点(根域名服务器)还找不到,即找不到该主机。
NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能
- NAT IP转换过程:
NAT路由器将源地址从10.0.0.10替换成全局的IP 202.244.174.37;
NAT路由器收到外部的数据时,又会把目标IP从202.244.174.37替换回10.0.0.10;
在NAT路由器内部,有一张自动生成的,用于地址转换的表;
当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系;- 如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中, 目的IP都是相同的。这时候NAPT来解决这个问题,使用IP+port来建立这个关联关系:这种关联关系也是由NAT路由器自动维护的。例如在TCP的情况下,建立连接时,就会生成这个表项; 在断开连接后,就会删除这个表项。
- 特点:有连接,可靠传输(核心特点),面向字节流,全双工。
- 格式:TCP报文 = TCP报头(首部) + TCP载荷
- 报头:
- 源/目的端口:用于区分一个主机上的具体应用程序,在同一个主机上一个端口不能被多个进程绑定。
- 32位序号/32位确认号:任何一条数据(包括应答报文)都是有序号的。确认序号只有应答报文有,普通报文确认序号字段里的值无意义。
- 4位TCP首部长度:一个TCP报头长度是可变的,首部长度的单位不是一个字节而是4个字节。
- 保留(6位)
- 6位标志位
URG标志位:
ACK标志位:1代表时应答报文,0代表不是应答报文。
PSH标志位:
RST标志位:
SYN标志位:标记客户端主动给服务器发起建立连接的请求的报文:同步报文段
FIN标志位:- 16位窗口大小:只在ACK报文中生效,16位并不意味着窗口大小是64KB,因为在选项中还有窗口扩展因子。
- 16位校验和
- 16位紧急指针
- 选项:相当于对这个TCP报文的属性进行解释说明,选项之前的部分是固定长度(20字节),首部长度减20字节就是选项部分的长度。包含窗口扩展因子,写明窗口大小左移位数,假如扩展因子写2,意思是 64KB << 2 =256KB 。
- 载荷:
即P数据报
- TCP状态:
- 建立连接时:
LISTEN:
服务器的状态。表示服务器已经准备就绪,随时可以有客户端来建立连接,相当于手机开机,信号良好,随时可以有人来打电话。
ESTABLISHED:
客户端和服务器都有,连接建立完成,接下来可以正常通信。
- 断开连接时:
CLOSE_WAIT:
出现在被动发起断开连接的一方,等待关闭(等待调用close方法关闭socket)。
TIME_WAIT:
出现在主动发起断开连接的一方。假设是客户端主动断开连接,当客户端进入TIME_WAIT状态的时候,相当于四次挥手已经挥完了。此时TIME_WAIT要保持当前的TCP连接状态不会立即释放,此时最后一个ACK刚刚发出去还没到,防止这个ACK丢包。如果最后一个ACK丢包了,站在服务器的角度看服务器不知道是因为ACK丢了还是自己发的FIN丢了所以统一视为FIN丢了,统一进行重传操作。服务器可能要重传FIN,客户端就需要能够针对这个重传的FIN进行ACK响应,因此使用TIME_WAIT状态保留一定的时间,就是为了能够处理最后一个ACK丢包的情况,能够在收到重传的FIN之后进行ACK响应。TIME_WAIT等了一段时间(2MSL)之后没有收到重传的FIN,就认为最后一个ACK没丢,于是彻底释放连接。
- 确认应答(安全机制,可靠传输的主要原因)
A给B发了个消息,B收到之后就会返回一个应答报文(ACK),A收到应答之后就知道刚才发的数据已经顺利到达B了。应答报文到达的顺序可能会发生变动,会出现后发先至的现象。所以引入 序号/确认序号,任何一条数据(包括应答报文)都是有序号的,确认序号只有应答报文有,普通报文确认序号字段里的值无意义。TCP报文字节的序号按照字节数来编号,每个TCP数据报报头填写的序号只需要写TCP数据的头一个字节的序号即可。A给B发送第一条数据,这条数据为1000字节,由于这条TCP数据报里的1000个字节都属于同一个TCP报文,TCP报头里就只记录当前数据报第一个字节的序号,此时报头的序号写的是1,这条报文的序号就是1。TCP报文的字节序号是依次累加的,A给B发送第二条数据,这条数据为1000字节,第二条TCP数据报的头一个字节的序号就相当于1001,最后一个字节序号是2000,由于1001~2000字节都是属于一个TCP数据报,此时报头的序号写的是1001,这条报文的序号就是1001,以此类推。
- 超时重传(安全机制,可靠传输的主要原因)
数据在传输过程中可能会丢包,可能时发送的数据丢了也可能时返回的ACK丢了。TCP引入了一个时间阈值,发送方发送了一个数据之后就开始等待ACK,此时开始计时,如果在时间阈值之内没有收到ACK则视为丢包,然后进行重传。重传的轮次越大超过时间间隔就越大,连续重传都丢包的概率很低否则很可能是网络出现了故障,重传达到一定次数就不会再继续重传,会认为网络出现了故障,接下来TCP会尝试重置连接(发送复位报文段RST)。每个TCP的Socket对象都有一个接收缓冲区(也有一个发送缓冲区,都可以视为一个有序队列),主机A给主机B发送数据,B的网卡读到数据把这个数据放到B对应的Socket缓冲区中,TCP使用这个接收缓冲区对收到的数据进行重新排序,并根据数据的序号识别缓冲区中的数据是否重复,如果重复则丢弃,使B读到的数据和A发送顺序一致且无重复。
- 连接管理(安全机制,可靠传输的次要因素)
- 建立连接(三次握手)
计算机中所谓的“连接”表示的是双方各自记录好对方的信息。三次握手本质是四次握手。首先客户端主动给服务器发起建立连接的请求,发送一个SYN报文段(同步报文段),服务器收到SYN报文段后会给客户端返回一个ACK,接着服务器给客户端发送一个SYN,然后服务器又给客户端发送一个SYN,最后客户端给服务器发送一个ACK。这个过程中服务器给客户端发的两次合并为一次交互,因此构成了“三次握手”。之所以合并是因为数据发送的过程中需要封装和分用,封装分用两次比一次成本更高。之所以能够合并是因为三次握手这三次交互是纯内核完成的,应用程序感知不到,也干预不了。中间的两次交互是同一时机,服务器的系统内核收到SYN之后就会立即发送ACK同时发送SYN。这三次握手验证通信双方各自的发送能力和接受能力是否正常,在握手的过程中双方来协商一些重要的参数,一定程度的保证了TCP传输的可靠性(起到的不是关键作用,起辅助作用)。
- 断开连接(四次挥手)
客户端向服务器发送FIN,FIN的发起不是由内核控制的,而是由应用程序调用socket的close方法(或者进程退出)才会触发FIN。然后服务器向客户端发送ACK,这个ACK是由内核控制的是收到FIN之后立即返回ACK,接着服务器向客户端发送FIN,这个FIN是服务器的应用程序执行到对应的close方法才会触发的FIN,服务器向客户端发送的ACK和FIN会有个时间差,具体时间长短看具体代码的写法,最后客户端向服务器发送ACK。
- 滑动窗口(效率机制)
在保证可靠性的基础上尽可能提高传输效率,本质是不等待的批量发送一组数据,然后使用一份时间来等待一组数据的多个ACK,数据会在TCP接收缓冲区里按序号重新排队,把不需要等待就能直接发送的数据的最大的量称为“滑动窗口”。到一个ACK就继续往下发一条,处等待的ACK始终都是固定的。对于丢包有两种情况,ACK丢了无影响,确认序号的含义表示从该序号往前的所有数据都已经确认到到达了,因为ACK并不是全部都发的,为了提高性能可能会故意少发一部分,同时会节省系统资源。如果数据丢了,当前传输数据密集的情况下,按照滑动窗口启动快速重传机制:只传输了丢失的数据,假如1001-2000丢包了,接下来2001-3000到达客户之后,客户端给主机返回的ACK确认序号仍然是1001(在索要1001开头的数据),然后对1001进行重传。在当前传输数据稀疏的情况下,按照之前超时重传处理丢包。
- 延时应答(效率机制)
收到数据后,不立即返回ACK,稍等一会儿再返回,等待的时间里,接收方的应用程序就能把接收缓冲区中的数据消费一部分,使剩余缓冲区空间更大,剩余空间的大小既取决于发送方的发送速度也取决于接收方的处理速度。实现方式是在滑动窗口下,ACK不再是每一条数据都返回。
- 流量控制(安全控制)
这是一种干预发送窗口大小的机制,根据接收方的处理能力协调发送方的发送速率。滑动窗口的窗口越大传输效率越高,但是整体效率受接收方的处理能力的约束,发送方发的速度不能超过接收方的处理能力。每次发送方给接收方发一个数据,接收方就算一下接收缓冲区的剩余空间,通过ACK报文(由16位窗口标记)返回给发送方,发送方根据这个值来决定接下来发送的速率是多少(窗口的大小是多少),接收方缓冲区剩余空间一直在动态变化,所以每次返回的ACK带的窗口大小都在变化,发送方也在动态调整,当窗口大小为0时,发送方就要暂停发送暂停发送的等待过程中,会给接收方定期发送窗口探测报文,这个报文不携带具体的业务数据,只是为了触发ACK查询窗口大小。
- 拥塞控制(安全机制)
描述的是传输过程中中间节点的处理能力,本质上是通过实验的方式逐渐找到一个合适的窗口大小(合适的发送速率),流量控制和拥塞窗口共同决定了发送方实际的发送窗口大小(取二者窗口中的较小的那个值)。
第0轮:窗口大小是1,以非常慢的速度发送数据(此处的1不是1字节,而是1单位)发现传输顺利没丢包窗口就扩大1倍。
第1轮:窗口大小是2,没有丢包窗口就扩大1倍。
…
初始阶段,由于窗口比较小,每一轮不丢包都会使窗口大小就会扩大1倍(指数增长),当增长速度达到一定阈值之后,指数增长就成为线性增长,当传输过程中一旦丢包了,则说明此时的发送速度已经接近网络的极限,此时就把窗口一下缩成很小的值,重复指数增长和线性增长的过程。
- 捎带应答(效率机制)
在延时应答的基础上引入捎带应答。实现方式:服务端B接收到客户端A发送的数据之后,服务端B回立即给客户端A返回一个ACK(由内核完成,立即返回),然后服务端B的应用程序会给客户端A返回一个响应(业务响应,比ACK慢),再此过程中,由于TCP存在延时应答机制,导致等待ACK的过程中,B就要给A发送业务数据了,于是就让业务数据捎上这个ACK一起发过去了。
- 粘包问题
接收缓冲区把收到的多个数据都放在一起了,TCP是字节流的,一次可以读任意字节(read方法是把数组尽可能填满),会导致一次读到的数据可能是半个应用层数据报,也可能是一个应用层数据报,也可能是多个应用层数据报,会造成读取的数据混乱。解决方案:约定好应用层协议,明确应用层数据报之间的边界,约定好分隔符并约定每个包的长度。
- 异常情况
- 进程崩溃:进程没了,对应的PCB就没了,对应的文件描述符表就释放了,相当于socket.close(),此时内核会继续完成四次挥手,此时是一个正常的断开流程
- 主机关机(按正常流程关机):主机关机要先杀死进程,然后才正式关机,杀死进程的过程中也是和上面一样触发四次挥手。
- 主机掉电/网线断开:
- 接收方掉电:发送方仍在继续发送数据,发送完数据继续等待ACK,等不到然后超时重传,多次重传没有应答尝试重置TCP连接(发送复位报文段RST),重置失败放弃连接(单方面放弃)。
- 发送方掉电:
接收方需要周期性的给发送方发送一个消息(心跳包),确认对方是否还正常工作【保活机制】,接收方发现没数据了然后的等待,超过一定时间之后就断开连接了。
- 格式:一个UDP报文=UDP报头+UDP载荷
UDP报头:
- 源端口:2字节
- 目的端口:2字节
- UDP报文长度:2字节,表示范围为:0 -> 65535,一个UDP数据报最大65535字节,约64KB。
- 校验和:2字节,发送方,把要发送的数据计算出校验和(checksum1),接收方,收到数据就把数据按照同样的方式再算一次校验和(checkdsum2),同时接收方也受到了checksum1,接收方对比checksum1和checksum2是否相同。
UDP载荷:应用层数据报
特点:无连接,不可靠,面向数据报,全双工,缓冲区,大小受限。
基于UDP的应用层协议:NFS,TFTP,DHCP,BOOTP,DNS.
扩展问题:
基于UDP协议实现可靠传输如何设计?
基于UDP协议传输超过64k的数据如何设计?
TCP优势在于可靠传输,UDP优势在于效率高,支持广播,适用于同一个机房内服务器之间的通信。
在复杂的网络环境中确定一个合适的路径。
IP协议格式:
- 4位版本号(version):
指定IP协议的版本,取值只有两个,对于IPv4来说,就是4,对IPv6来说就是6。- 4位头部长度(header length):
描述了IP报头的长度是多少(有多少个32bit)(报头中有一个选项部分,IP报头长度是可变的),单位为4字节。4bit表示最大的数字是15,因此IP头部最大长度是60字节。
- 8位服务类型(TOS / Type Of Service):
只有4位有效,4位TOS字段表示IP协议的四种形态/工作模式,其他位都是0(3位优先权字段(已经弃用)和1位保留字段(必须置为0))
四种形态/工作模式:
最小延时,最大吞吐量,最高可靠性,最小成本,这四者相互冲突,只能选择一个。
对于ssh/telnet这样的应用程序,最小延时比较重要;
对于ftp这样的程序,最大吞吐量比较重要。
- 16位总长度(total length):
IP数据报整体占多少个字节(报头+载荷),216=65536 ,一个IP数据报最大只能支持64KB。如果一个IP数据报携带的数据报载荷超过了64KB,就会在网络层对数据进行拆分,把一个数据拆成多个IP数据报,再分别发送,接收方收到之后重新拼装
- 案例:
发送方:
把100KB的数据交给传输层(封装),传输层交给网络层(封装),网络层就把这100KB的数据包拆包(假如拆成两份)64KB+36KB,网络层把这两份交给数据链路层,由以太网分装成两个数据帧(IP协议拆包不一定按照64KB为单位进行拆分,实际的单位会更小,具体取决于数据链路层的情况)。
接收方:
数据链路层针对两个数据帧进行分用得到两个IP数据报,交给网络层,网络层针对这两个IP数据报进行解析,把里面的载荷拼成一个,交给传输层,传输层再交给应用层。
- 16位标识(id):
唯一的标识主机发送的报文,同一个数据包拆成多个包标识是一样的。(辅助拆包组包)
如果IP报文在数据链路层被分片了,那么每一个片里面的这个id都是相同的。- 3位标志字段:结束标志
第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。
第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。
第三位表示"更多分片",如果分片了的话,最后一个分片置为1,其他是0,类似于一个结束标记。 (辅助拆包组包)- 13位分片偏移(framegament offset):标识了多个包的先后顺序。(辅助拆包组包)
是分片相对于原始IP报文开始处的偏移。其实就是在表示当前分片在原报文中处在哪个位置。
实际偏移的字节数是这个值 * 8 得到的。因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)。- 8位生存时间(Time To Live,TTL):数据报到达目的地的最大报文跳数,一个数据包在网络上能够传输的最大时间,单位是次数。
一个数据报构造出来会有一个初始的TTL数值,一般是64,这个报每经过一个路由器转发,TTL-1,一直减到0还没到达那么就丢弃了,这个字段主要用来防止出现路由循环。- 8位协议:表示上层协议的类型,
描述了当前载荷部分是属于TCP还是UDP- 16位头部校验和:使用CRC进行校验,来鉴别头部是否损坏。
只针对首部进行校验(载荷部分(TCP/UDP)自身已经有校验和了),如果校验和不一致直接丢弃(IP不负责重传),如果上层使用TCP,TCP会在收到ACK之后就重传。- 32位源地址和32位目标地址:
表示发送端和接收端。- 选项字段(不定长,最多40字节)。
- 来源:
IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址,是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
- 用途:
用于定位主机(如网络主机、路由器等其他网络设备)的网络地址,描述的是路途总体的起点和终点,是给人使用的网络逻辑地址。
- 构成
- 网络号:
标识网段,保证互相连接的两个网段(局域网)具有不同的标识。- 主机号:
标识主机,同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。- 子网掩码:
划分A,B,C三类 IP 地址子网
- 格式
IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”,也就是4个字节,通常用“点分十进制”的方式来表示。使用三个 . 把一共32位,分成4个部分,每个部分占一个字节,分别使用0-255十进制整数表示。即 a.b.c.d 的形式(a,b,c,d都是0~255之间的十进制整数)如:01100100.00000100.00000101.00000110 ——> 100.4.5.6。
- 数量
- IPv4:
IPv4数量=2^32,大约43亿左右,而TCP/IP协议规定,每个主机都需要有一个IP地址。对于全世界计算机来说,这个数量是不够的。解决办法:
- IPv6:
长度128位,是IPv4的4倍,但因为目前IPv4还广泛的使用,所以IPv6也就没有普及。- 动态分配IP地址,没有从根本上增加IP地址,只是提高了利用率
- NAT网络地址转换
- 分类
各类地址的表示范围是:
在上述的分类中,存在IP地址浪费的问题:
- 单位一般会申请B类网络(C类连接主机数量有限),但实际网络架设时,连接的主机数量又常远小于65534(B类连接主机数),造成IP地址浪费;同理,A类网络的IP地址也会造成大量的浪费。
- 当一个单位申请了一个网络号。他想将该网络能表示的IP地址再分给它下属的几个小单位时,如果在申请新的网络就会造成浪费。
为了解决以上问题,引入子网掩码来进行子网划分
- 子网掩码
- 格式
是一个32位的二进制数。其中左边是网络位,用二进制数字“1”表示,1
的数目等于网络位的长度;右边是主机位,用二进制数字“0”表示,0的数目等于主机位的长度。子网掩码也可以使用二进制所有高位1相加的数值来表示- 作用
- 划分A,B,C三类 IP 地址子网
- 一般用于判断目的IP与本IP是否为同一个网段
- 计算方式
将 IP 地址和子网掩码进行“按位与”操作(二进制相同位,与操作,两个都是1结果为1,否则为0),得到的结果就是网络号。将子网掩码二进制按位取反,再与 IP 地址位与计算,得到的就是主机号
示例:
特殊IP:
- 127.*的IP地址用于本机环回测试(loop back),通常是127.0.0.1。(本机环回主要用于本机到本机的网络通信(系统内部为了性能,不会走网络的方式传输),对于开发网络通信的程序(即网络编程)而言,常见的开发方式都是本机到本机的网络通信)
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网.
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包;
- 什么是MAC地址:Media Access Control Address,用于标识网络设备的硬件物理地址
网络通信(网络数据传输)本质上是网络硬件设备将数据发送到网卡上或从网卡接收数据。主机具有一个或多个网卡,路由器具有两个或两个以上网卡,其中每个网卡都有唯一的一个MAC地址。- MAC地址的作用:硬件层面能基于MAC地址识别网络设备的网络物理地址。
- MAC地址与IP地址的区别:
IP地址描述的是网络通信路途总体的起点和终点;是给人使用的网络逻辑地址。
MAC地址描述的是网络通信路途上的每一个区间的起点和终点,是给网络硬件设备使用的网络物理地址。
ARP不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议。
- ARP协议的作用:ARP协议建立了主机 IP地址和MAC地址的映射关系。
在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬
件地址;数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃;因此在通讯前必须获得目的主机的硬件地址。- ARP协议的工作流程:
- 源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”,并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播)。
- 目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中。
- 每台主机都维护一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址。
- 一跳一跳的网络数据传输:
对于网络数据传输,不是想象中那样,数据直接从源主机到达目的主机,而是类似在地图中,从A到B的过程,例如:
唐僧去西天取经,行程为长安、五指山、黑风山、女儿国……大雷音寺。
IP地址描述的是路途总体的起点和终点:源IP就是整个行程的起点:长安;目的IP对应为整个行程的终点:大雷音寺。
行进必须一个地点一个地点的前进,由MAC地址来描述路途上每一个区间的起点和终点:从长安到五指山,为一跳的区间,源MAC为长安,目的MAC为五指山;从五指山到黑风山,为下一跳的区间,源MAC为五指山,目的MAC为黑风山。
对于以上经过的网络设备:
主机:配有IP地址,但是不进行路由控制的设备
路由器:即配有IP地址,又能进行路由控制
节点:主机和路由器的统称
集线器和二层交换机不会对数据报封装和分用,不算在下一跳设备
- 什么是以太网?
“以太网” 不是一种具体的网络,而是一种技术标准,既包含了数据链路层的内容,也包含了
一些物理层的内容。例如:规定了网络拓扑结构,访问控制方式,传输速率等;
例如以太网中的网线必须使用双绞线;传输速率有10M,100M,1000M等;
以太网是当前应用最广泛的局域网技术;和以太网并列的还有令牌环网,无线LAN等;
- 以太网帧格式:帧头(目的地址,源地址,类型),载荷,帧尾
- 源地址和目的地址是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固化的;
- 帧协议类型字段有三种值,分别对应IP、ARP、RARP;
- 帧末尾是CRC校验码。
- MTU:是不同的数据链路对应的物理层对以太网帧产生的限制,相当于发快递时对包裹尺寸的限制。
以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要在后面补填充位;最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation),不同的数据链路层标准的MTU是不同的。- MTU对IP协议的影响
- MTU对UDP协议的影响
- MTU对TCP协议的影响
网络数据传输过程中经过不同的网络节点(主机、路由器等)时,网络分层需要与协议分层一 一对应。
示例一:
同一个网段内的两台主机进行文件传输:
示例二:
跨网段的主机的文件传输:数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器
不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation)。首部信息中包含了一些类似于首部有多长,载荷(payload)有多长,上层协议是什么等信息。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的 “上层协议字段” 将数据交给对应的上层协议处理。
集线器是工作在物理层的网络设备,发送到集线器的任何数据,都只是简单的将数据复制并转发到其他 所有端口。(端口指集线器后边的物理端口)
交换机工作在数据链路层,交换机内部会记录并维护一张MAC地址转换表,MAC地址转换表主要记录MAC地址与端口之间的映射。(端口指交换机后边的物理端口),主机连接到交换机,及主机发送数据的时候,交换机可以学习并记录该主机MAC地址与端口信息。交换机接收到数据报以后,在MAC地址转换表中,通过目的MAC查找到对应的端口,则目的主机为该端口相连接的主机。只需要将数据报转发到对应端口上即可。如果找不到,交换机设置数 据报目的MAC为广播地址FF:FF:FF:FF:FF:FF,发送到其他所有端口,目的主机返回响应后,交换机再记录该主机MAC与端口的映射信息。
IP地址描述的是路途总体的起点和终点;是给人使用的网络逻辑地址。
IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。
IP地址是IP协议提供的一种统一的地址格式,
它为互联网上的每一个网络和每一台主机分配一个逻辑地址,
以此来屏蔽物理地址的差异。
IP地址是一个32位的二进制数,
通常被分割为4个“8位二进制数”(也就是4个字节),如:01100100.00000100.00000101.00000110。
通常用“点分十进制”的方式来表示,即 a.b.c.d 的形式(a,b,c,d都是0~255之间的十进制整数)。如:
100.4.5.6。
IPv4数量=2^32,大约43亿左右,而TCP/IP协议规定,每个主机都需要有一个IP地址。
对于全世界计算机来说,这个数量是不够的,所以后来推出了IPv6(长度128位,是IPv4的4倍)。
但因为目前IPv4还广泛的使用,且可以使用其他技术来解决IP地址不足的问题,所以IPv6也就没有普及。
构成
IP地址分为两个部分,网络号和主机号。
网络号:
标识网段,保证相互连接的两个网段具有不同的标识;
主机号:
标识主机,同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号;
分类
子网掩码
MAC地址描述的是路途上的每一个区间的起点和终点,即每一跳的起点和终点;
是给网络硬件设备使用的网络物理地址。
MAC地址,即 Media Access Control Address,用于标识网络设备的硬件物理地址。
主机具有一个或多个网卡,路由器具有两个或两个以上网卡;
其中每个网卡都有唯一的一个MAC地址。
主机具有一个或多个网卡,路由器具有两个或两个以上网卡;
其中每个网卡都有唯一的一个MAC地址。
硬件层面,只能基于MAC地址识别网络设备的网络物理地址。
MAC地址用来识别数据链路层中相连的节点;
长度为48位,及6个字节。一般用16进制数字加上冒号的形式来表示(例如:08:00:27:03:fb:19)
在网卡出厂时就确定了,不能修改。虚拟机中的MAC地址不是真实的MAC地址,可能会冲突;
也有些网卡支持用户配置MAC地址。
特殊的MAC地址:发送一个广播数据报,表示对同网段所有主机发送数据报。
广播数据报的MAC地址为:FF:FF:FF:FF:FF:FF。
以下为主机B传输数据到主机C经过的网络设备:
对于以上经过的网络设备:
主机:
配有IP地址,但是不进行路由控制的设备。
路由器:
即配有IP地址,又能进行路由控制。
节点:
主机和路由器的统称。
集线器和二层交换机不会对数据报封装和分用,不算在下一跳设备。
对于网络数据传输,不是想象中那样,数据直接从源主机到达目的主机,而是类似在地图中,从A到B的过程。
IP地址描述的是路途总体的起点和终点,而行进也必须一个地点一个地点的前进,由MAC地址来描述路途上每一个区间的起点和终点。
使用集线器网络互联的情况下,发送端主机发送数据包时,需要先从上到下封装数据报。但封装时,目的MAC可能并不知道,需要先进行ARP寻址:
以下为本机ARP缓存表能找到目的MAC的流程:
请说明浏览器中输入url后,发生的事情,越详细越好?
DNS,即Domain Name System,域名系统。
DNS是一整套从域名映射到IP的系统。
TCP/IP中使用IP地址来确定网络上的一台主机,
但是IP地址不方便记忆,且不能表达地址组织信息,
于是人们发明了域名,并通过域名系统来映射域名和IP地址。
域名是一个字符串,如 www.baidu.com ,hr.nowcoder.com
域名系统为一个树形结构的系统,包含多个根节点。其中:
网络通信发送数据时,如果使用目的主机的域名,
需要先通过域名解析查找到对应的IP地址:
域名解析的过程,可以简单的理解为:
发送端主机作为域名系统树形结构的一个子节点,通过域名信息,从下到上查找对应IP地址的过程。
如果到根节点(根域名服务器)还找不到,即找不到该主机。
域名解析使用DNS协议来传输数据。DNS协议是应用层协议,基于传输层UDP或TCP协议来实现。
NAT路由器将源地址从10.0.0.10替换成全局的IP 202.244.174.37;
NAT路由器收到外部的数据时,又会把目标IP从202.244.174.37替换回10.0.0.10;
在NAT路由器内部,有一张自动生成的,用于地址转换的表;
当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系。
NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能。
NAT能够将私有IP对外通信时转为全局IP。
也就是就是一种将私有IP和全局IP相互转化的技术方法。
很多学校,家庭,公司内部采用每个终端设置私有IP,而在路由器或必要的服务器上设置全局IP。
全局IP要求唯一,但是私有IP不需要;
在不同的局域网中出现相同的私有IP是完全不影响的。
如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的IP都是相同的。
NAPT来解决这个问题。
使用IP+port来建立这个关联关系。
这种关联关系也是由NAT路由器自动维护的。例如在TCP的情况下,建立连接时,就会生成这个表项;在断开连接后,就会删除这个表项。
NAT技术的缺陷 :
由于NAT依赖这个转换表,所以有诸多限制:
无法从NAT外部向内部服务器建立连接。
转换表的生成和销毁都需要额外开销。
通信过程中一旦NAT设备异常,即使存在热备,所有的TCP连接也都会断开。
传输层的作用:负责数据能够从发送端传输接收端。
TCP,即Transmission Control Protocol,传输控制协议,要对数据的传输进行一个详细的控制。
源/目的端口号:
表示数据是从哪个进程来,到哪个进程去。
32位序号/32位确认号:
4位TCP报头长度:
表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60。
6位标志位:
16位窗口大小:
16位校验和:
发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。。
此处的检验和不光包含TCP首部,也包含TCP数据部分。
16位紧急指针:
标识哪部分数据是紧急数据。
40字节头部选项:
TCP对数据传输提供的管控机制,主要体现在两个方面:安全和效率。
这些机制和多线程的设计原则类似:
保证数据传输安全的前提下,尽可能的提高传输效率。
确认应答机制(安全机制)
TCP将每个字节的数据都进行了编号,即为序列号。
每一个ACK都带有对应的确认序列号,
意思是告诉发送者,我已经收到了哪些数据;
下一次你从哪里开始发。
超时重传机制(安全机制)
主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B。
如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。
但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了。
因此主机B会收到很多重复数据。
那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。
这时候可以利用前面提到的序列号,就可以很容易做到去重的效果。
如何确定超时的时间?
最理想的情况下,找到一个最小的时间,保证 “确认应答一定能在这个时间内返回”。
但是这个时间的长短,随着网络环境的不同,是有差异的。
如果超时时间设的太长,会影响整体的重传效率;
如果超时时间设的太短,有可能会频繁发送重复的包。
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。
Linux中(BSD Unix和Windows也是如此),
超时以500ms为一个单位进行控制,
每次判定超时重发的超时时间都是500ms的整数倍。
如果重发一次之后,仍然得不到应答,
等待 2500ms 后再进行重传。
如果仍然得不到应答,等待 4500ms 进行重传。
依次类推,以指数形式递增。
累计到一定的重传次数,
TCP认为网络或者对端主机出现异常,强制关闭连接。
在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。
较粗的虚线表示服务端的状态变化情况;
较粗的实线表示客户端的状态变化情况;
CLOSED是一个假想的起始点,不是真实状态;
服务端状态转化:
[CLOSED -> LISTEN] :
服务器端调用listen后进入LISTEN状态,等待客户端连接。
[LISTEN -> SYN_RCVD] :
一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列中,并向客户端发送SYN确认报文。
[SYN_RCVD -> ESTABLISHED]:
服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,可以进行读写数据了。
[ESTABLISHED -> CLOSE_WAIT] :
当客户端主动关闭连接(调用close),服务器会收到结束报文段,服务器返回确认报文段并进CLOSE_WAIT。
[CLOSE_WAIT -> LAST_ACK] :
进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据);
当服务器真正调用close关闭连接时,会向客户端发送FIN,
此时服务器进入LAST_ACK状态,等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)。
[LAST_ACK -> CLOSED] :
服务器收到了对FIN的ACK,彻底关闭连接。
客户端状态转化:
[CLOSED -> SYN_SENT]:
客户端调用connect,发送同步报文段。
[SYN_SENT -> ESTABLISHED] :
connect调用成功,则进入ESTABLISHED状态,开始读写数据。
[ESTABLISHED -> FIN_WAIT_1] :
客户端主动调用close时,向服务器发送结束报文段,同时进入FIN_WAIT_1。
[FIN_WAIT_1 -> FIN_WAIT_2] :
客户端收到服务器对结束报文段的确认,则进入FIN_WAIT_2,开始等待服务器的结束报文段。
[FIN_WAIT_2 -> TIME_WAIT] :
客户端收到服务器发来的结束报文段,进入TIME_WAIT,并发出LAST_ACK。
[TIME_WAIT -> CLOSED] :
客户端要等待一个2MSL(Max Segment Life,报文最大生存时间)的时间,才会进入CLOSED状态。
MSL是TCP报文的最大生存时间,因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到来自上一个进程的迟到的数据,但是这种数据很可能是错误的)。
同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失,那么服务器会再重发一个FIN。这时虽然客户端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ACK)。
滑动窗口(效率机制)
这种机制被称为 “高速重发控制”(也叫 “快重传”)。
对每一个发送的数据段,都要给一个ACK确认应答。
收到ACK后再发送下一个数据段。
这样做有一个比较大的缺点,就是性能较差。
尤其是数据往返的时间较长的时候。
既然这样一发一收的方式性能较低,那么我们一次发送多条数据,
就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)。
窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节(四段)。
发送前四个段的时候,不需要等待任何ACK,直接发送。
收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据。
依次类推;操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;窗口越大,则网络的吞吐率就越高。
情况一:数据包已经抵达,ACK被丢了。
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;
当某一段报文段丢失之后,发送端会一直收到 1001 这样的ACK,
就像是在提醒发送端 “我想要的是 1001” 一样。
如果发送端主机连续三次收到了同样一个 “1001” 这样的应答,就会将对应的数据 1001 - 2000 重新发送。
这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中。
流量控制(安全机制)
接收端处理数据的速度是有限的。
如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。
因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制(Flow Control)。
接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段,通过ACK端通知发送端。
窗口大小字段越大,说明网络的吞吐量越高。
接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端。
发送端接受到这个窗口之后,就会减慢自己的发送速度。
如果接收端缓冲区满了,就会将窗口置为0。
这时发送方不再发送数据,但是需要定期发送一个窗口探测数段,使接收端把窗口大小告诉发送端。
接收端如何把窗口大小告诉发送端呢?
TCP首部中,有一个16位窗口字段,就是存放了窗口
大小信息。
那么问题来了,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?
实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移 M位。
拥塞控制(安全机制)
TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输据。
此处引入一个概念为拥塞窗口。
发送开始的时候,定义拥塞窗口大小为1,
每次收到一个ACK应答,拥塞窗口加1,
每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口。
像上面这样的拥塞窗口增长速度,是指数级别的。
“慢启动” 只是指初使时慢,但是增长速度非常快。
为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。
此处引入一个叫做慢启动的阈值。
当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。
当TCP开始启动的时候,慢启动阈值等于窗口最大值。
在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1。
少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞。
当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降。
拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。
延迟应答(效率机制)
如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小。
假设接收端缓冲区为1M。一次收到了500K的数据;如果立刻应答,返回的窗口就是500K;
但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了;
在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来;
如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M。
一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。
那么所有的包都可以延迟应答么?肯定也不是;
数量限制:每隔N个包就应答一次;
时间限制:超过最大延迟时间就应答一次。
具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms。
捎带应答(效率机制)
在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 “一发一收” 的。
意味着客户端给服务器说了 “How are you”,服务器也会给客户端回一个 “Fine, thank you”;
那么这个时候ACK就可以搭顺风车,和服务器回应的 “Fine,thank you” 一起回给客户端。
面向字节流
缓冲区
大小限制
创建一个TCP的socket,同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区。
调用write时,数据会先写入发送缓冲区中;
如果发送的字节数太长,会被拆分成多个TCP的数据包发出。
如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去。
接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区。
然后应用程序可以调用read从接收缓冲区拿数据。
另一方面,TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据。这个概念叫做 全双工。
由于缓冲区的存在,TCP程序的读和写不需要一一匹配,例如:
写100个字节数据时,可以调用一次write写100个字节,也可以调用100次write,每次写一个字节。
读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read 100个字节,也可以一次read一个字节,重复100次。
首先要明确,粘包问题中的 “包” ,是指的应用层的数据包。
在TCP的协议头中,没有如同UDP一样的 “报文长度” 这样的字段,但是有一个序号这样的字段。
站在传输层的角度,TCP是一个一个报文过来的。按照序号排好序放在缓冲区中。
站在应用层的角度,看到的只是一串连续的字节数据。
首先要明确,粘包问题中的 “包” ,是指的应用层的数据包。
在TCP的协议头中,没有如同UDP一样的 “报文长度” 这样的字段,但是有一个序号这样的字段。
站在传输层的角度,TCP是一个一个报文过来的。按照序号排好序放在缓冲区中。
站在应用层的角度,看到的只是一串连续的字节数据。
那么如何避免粘包问题呢?
对于定长的包,保证每次都按固定大小读取即可;例如上面的Request结构,是固定大小的,那么就从缓冲区从头开始按sizeof(Request)依次读取即可;
对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可)。
对于UDP协议来说,是否也存在 “粘包问题” 呢?
对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。
同时,UDP是一个一个把数据交付给应用层。就有很明确的数据边界。
站在应用层的站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收。不会出现"半个"的情况。
进程终止:
进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别。
机器重启:
和进程终止的情况相同。
机器掉电/网线断开:
接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset。
即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在。
如果对方不在,也会把连接释放。
另外,应用层的某些协议,也有一些这样的检测机制。例如HTTP长连接中,也会定期检测对方的状态。
例如QQ,在QQ断线之后,也会定期尝试重新连接。
HTTP
HTTPS
SSH
Telnet
FTP
SMTP
传输层的作用:负责数据能够从发送端传输接收端。
16位UDP长度,表示整个数据报(UDP首部+UDP数据)的最大长度。
如果校验和出错,就会直接丢弃。
无连接
知道对端的IP和端口号就直接进行传输,不需要建立连接。
不可靠
没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。
面向数据报
应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
用UDP传输100个字节的数据,如果发送端一次发送100个字节,那么接收端也必须一次接收100个字节;而不能循环接收10次,每次接收10个字节。
缓冲区
UDP的socket既能读,也能写,这个概念叫做 全双工。
UDP只有接收缓冲区,没有发送缓冲区。
UDP没有真正意义上的 发送缓冲区。
发送的数据会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致。
如果缓冲区满了,再到达的UDP数据就会被丢弃。
大小受限
UDP协议首部中有一个16位的最大长度。
也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)。
NFS:网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议(用于无盘设备启动)
DNS:域名解析协议
也包括自己写UDP程序时自定义的应用层协议。
UDP本身是无连接,不可靠,面向数据报的协议,如果要基于传输层UDP协议,来实现一个可靠传
输,应该如何设计?
UDP大小是受限的,如果要基于传输层UDP协议,传输超过64K的数据,应该如何设计?
以上两个问题答案类似,都可以参考TCP的可靠性机制在应用层实现类似的逻辑:
例如:
引入序列号,保证数据顺序;
引入确认应答,确保对端收到了数据;
引入超时重传,如果隔一段时间没有应答,就重发数据;
……
在复杂的网络环境中确定一个合适的路径。
4位版本号(version):
指定IP协议的版本,对于IPv4来说,就是4。
4位头部长度(header length):
IP头部的长度是多少个32bit,也就是 length * 4 的字节
数。
4bit表示最大的数字是15,因此IP头部最大长度是60字节。
8位服务类型(Type Of Service):
3位优先权字段(已经弃用),4位TOS字段,和1位保留字段(必须置为0)。
4位TOS分别表示:
最小延时,最大吞吐量,最高可靠性,最小成本。
这四者相互冲突,只能选择一个。
对于ssh/telnet这样的应用程序,最小延时比较重要;
对于ftp这样的程序,最大吞吐量比较重要。
16位总长度(total length):
IP数据报整体占多少个字节。
16位标识(id):
唯一的标识主机发送的报文。
如果IP报文在数据链路层被分片了,那么每一个片里面的这个id都是相同的。
3位标志字段:
第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。
第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。
第三位表示"更多分片",如果分片了的话,最后一个分片置为1,其他是0,类似于一个结束标记。
13位分片偏移(framegament offset):
是分片相对于原始IP报文开始处的偏移。
其实就是在表示当前分片在原报文中处在哪个位置。
实际偏移的字节数是这个值 * 8 得到的。
因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)。
8位生存时间(Time To Live,TTL):
数据报到达目的地的最大报文跳数。
一般是64。每次经过一个路由,TTL -= 1,一直减到0还没到达,那么就丢弃了。
这个字段主要是用来防止出现路由循环。
8位协议:
表示上层协议的类型。
16位头部校验和:
使用CRC进行校验,来鉴别头部是否损坏。
32位源地址和32位目标地址:
表示发送端和接收端。
选项字段(不定长,最多40字节)。
数据链路层的作用:
两个设备(同一种数据链路节点)之间进行传递数据。
“以太网” 不是一种具体的网络,而是一种技术标准;
既包含了数据链路层的内容,也包含了一些物理层的内容。
例如:规定了网络拓扑结构,访问控制方式,传输速率等;
例如以太网中的网线必须使用双绞线;
传输速率有10M,100M,1000M等;
以太网是当前应用最广泛的局域网技术;
和以太网并列的还有令牌环网,无线LAN等。
源地址和目的地址是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固化的。
帧协议类型字段有三种值,分别对应IP、ARP、RARP。
帧末尾是CRC校验码。
MTU相当于发快递时对包裹尺寸的限制。
这个限制是不同的数据链路对应的物理层,产生的限制。
以太网帧中的数据长度规定最小46字节,最大1500字节,
ARP数据包的长度不够46字节,要在后面补填充位。
最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU。
如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation)。
不同的数据链路层标准的MTU是不同的。
MTU对IP协议的影响 :
由于数据链路层MTU的限制,
对于较大的IP数据包要进行分包。
将较大的IP包分成多个小包,并给每个小包打上标签。
每个小包IP协议头的 16位标识(id) 都是相同的。
每个小包的IP协议头的3位标志字段中,第2位置为0,表示允许分片,第3位来表示结束标记(当前是否是最后一个小包,是的话置为1,否则置为0)。
到达对端时再将这些小包,会按顺序重组,拼装到一起返回给传输层。
一旦这些小包中任意一个小包丢失,接收端的重组就会失败。但是IP层不会负责重新传输数据。
MTU对UDP协议的影响
一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)),那么就会在网络层分成多个IP数据报。
这多个IP数据报有任意一个丢失,都会引起接收端网络层重组失败。
那么这就意味着,如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了。
MTU对于TCP协议的影响 :
TCP的一个数据报也不能无限大,还是受制于MTU。
TCP的单个数据报的最大消息长度,称为MSS(Max Segment Size)。
TCP在建立连接的过程中,通信双方会进行MSS协商。
最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU)。
双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值。
然后双方得知对方的MSS值之后,选择较小的作为最终MSS。
MSS的值就是在TCP首部的40字节变长选项中(kind=2)。
ARP不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议。
ARP协议的作用:
ARP协议建立了主机 IP地址 和 MAC地址 的映射关系。
在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址。
数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃。
因此在通讯前必须获得目的主机的硬件地址。
ARP协议的工作流程
源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”,
并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示播)。
目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,
则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中。
每台主机都维护一个ARP缓存表,可以用arp -a命令查看。
缓存表中的表项有过期时间(一般为20分钟),
如果20分钟内没有再次使用某个表项,则该表项失效,
下次还要发ARP请求来获得目的主机的硬件地址。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。