内容简介:近期工作,跟网络协议相关,这让我有机会更深入学习网络协议,而之前很长一段时间,我对网络协议的理解都停留在比较浅的层面。比如:TCP是面向连接的、可靠传输,而UDP是非连接的、不可靠传输,TCP建连需要3次握手,会造成delay,UDP更快。比如:socket编程,服务器socket create、bind、listen、accept、read/write、shutdown/close,客户端socket create、connect、read/write、shutdown/close,再加上epoll/se
近期工作,跟网络协议相关,这让我有机会更深入学习网络协议,而之前很长一段时间,我对网络协议的理解都停留在比较浅的层面。
比如:TCP是面向连接的、可靠传输,而UDP是非连接的、不可靠传输,TCP建连需要3次握手,会造成delay,UDP更快。
比如:socket编程,服务器socket create、bind、listen、accept、read/write、shutdown/close,客户端socket create、connect、read/write、shutdown/close,再加上epoll/select这几下子。
再比如:我知道网络编程要忽视SIGPIPE信号不然会挂,read返回0代表对端主动关闭,非阻塞的read要放在循环里要考虑返回值,多路复用以及阻塞、非阻塞的区别。
TCP/UDP的区别上,我是这样理解的:从北京到杭州,TCP相当于修了一条高铁线路(建连)再通车发货(传输数据),而UDP相当于寄快递,丢了不管(直接传输数据)。
上面的理解对不对?可以说对,也可以说不对。对于应用 程序员 来说,有了上面的认识+熟悉socket编程接口,够了吗?不够吗?
大物理学家费曼提出一个高效的费曼学习法,即从问题入手,试着把问题都讲出来,以教代学,一旦你能把问题都讲清楚,便学会了。所以我想尝试一下把TCP/IP讲清楚,借此让自己学明白,顺便帮助一下读者。
虽然《TCP/IP详解卷1》是一本关于互联网协议族很严谨详尽的书,但在我看来,它稍微有点晦涩,可能需要读几遍,才能心领神会。虽然我没有能力把这个问题说的更好,但因为我经历过从稀里糊涂到稍有所悟的过程,这可能是大师不可比的,我将尽量用通俗易懂的语言把TCP/IP相关的知识讲清楚。
TCP/IP是什么
TCP/IP协议族是一组协议的集合,也叫互联网协议族,用来实现互联网上主机之间的相互通信。TCP和IP只是其中的2个协议,也是很重要的2个协议,所以用TCP/IP来命名这个互联网协议族,实际上,它还包括其他协议,比如UDP、ICMP、IGMP、ARP/RARP等。
网络分层
大学《计算机网络》教科书上有经典的网络ISO七层模型,但七层划分太细了,稍显繁琐,不容易记住。
互联网协议族TCP/IP按粗粒度的四层划分,两种划分的对照图让彼此关系一目了然。
分层是计算机领域的常用技巧,比如互联网后端的三层架构“接入-逻辑-存储”就是分层思想的典型应用。
分层是为了隔离,通过分层划分职能,拆解问题,层与层之间约定接口,屏蔽实现细节。
TCP/IP自下到上划分为链路层、网络层、传输层、应用层。下层向上层提供能力,上层利用下层的能力提供更高的抽象。
- 链路层,也称网络接口层,包括操作系统的设备驱动程序和网卡,它们一起处理与传输媒介(光纤等)的物理接口细节。
- 网络层,也就是IP层,负责处理IP datagram在网络中的传输,IP层传输的是IP datagram,借助路由表,把IP datagram从网络的一端传输到另一端,简而言之:IP实现包的路由传输,IP协议和路由器工作在网络层。
- 传输层,提供端到端之间的通信,包括提供面向连接和高可靠性的TCP,以及无连接不可靠的UDP。貌似TCP更好,但实际不是这样,UDP因为不需要建连开销,所以更快,应用得也很广,比如新一代互联网协议HTTP3就从TCP转向UDP,应根据适应场景选择传输层协议。
- 应用层,跟应用相关,不同应用解决不同问题,需要不同的应用层协议。
链路层处理数据在媒介上的传输,以及主机与网卡、光纤等打交道的细节。因为与硬件相关,所以需要借助系统的驱动程序,链路层协议就是定义这些细节的,比如怎么把数据从网卡发送到光纤,采用什么格式编码等,它解决的数据在媒介上表示、流动的问题。
光有链路层功能肯定是不够的,网络上有成千上万的机器,主机A与B通信,你不能将数据发到主机C,所以仿照现实,要为主机分配网络地址,通过IP地址去标识网络中的一台主机,发送一个数据包,需要正确路由到目的地,这就好比你从家到公司,要经过哪些路径,需要地图,而路由表就类似这张地图。IP解决的是数据包在网络中的传输路由的问题。
有了网络层的传输路由能力,还不够,因为IP报在传输过程中可能丢包,比如中间经历过的路由器缓冲区满了便会丢包,这样不可靠,如果需要可靠传输的能力,便需要传输层基于IP层,提供更多的能力,TCP解决了可靠性问题。具体而言,如果丢包了,TCP层会负责超时重传,它通过接收确认和重传机制保证了可靠传输。另外,因为IP报都是独立路由的,所以从主机A到主机B,一份数据被拆分成x、y两个IP报先后发送,这2个包可能选择不同的传输路径,这样有可能y包先于x包到达,但我们希望在接收端(主机B)恢复这个数据的信息,但我们无法控制IP报的到达顺序,所以,我们需要在接收端恢复数据,我只需要在x、y包里记录它属于数据块的哪个部分,然后重组这份数据,这正是TCP做的,它会重新组装IP报,从而保证顺序性,递交给应用层。
有时候并不需要保证可靠性和顺序性,这便是UDP能提供的,它只是简单的把数据封装成IP报,然后通过IP层路由发送到目的端。
再往上,便是应用层协议了,比如http,又比如游戏服务器自定义协议,应用层协议通常基于TCP或者UDP做传输。
分层
什么是协议?懒得去翻协议的各种权威定义了,我认为协议就是约定,跟现实生活中协议这个词含义差不多。网络协议就是通信双方共同遵守的约定,更具体一点,就是定义数据在网络上传输的格式、规则和流程。
因为网络是分层模型,不同层有不同层的作用,所以为各层定义各层的规则,各层对应的各层协议。
前面讲了TCP/IP协议族包含很多协议,这些协议分属不同的分层,承担不同的作用。
- TCP和UDP是两种主要的传输层协议。
- IP是网络层的主要协议,TCP、UDP都需要利用IP协议进行数据传输。
- ICMP是互联网控制报文协议,是IP的附属协议,IP层用它来与其他主机或路由器交换错误报文和其他重要信息。比如一个Packet经过某个路由器节点的时候,超过网络对Packet的长度限制,而又不分片,则会给发送端发送一个ICMP包报告错误信息,属于ICMP是用来辅助IP完成数据包传输的。
- IGMP是Internet组管理协议,用来把一个包多播到多个主机。
- ARP(地址解析协议)和RARP(逆地址解析协议)是用来转换IP层和链路层的地址,IP层使用IP地址,链路层使用Mac地址
- 应用层和传输层使用端到端(end-to-end)协议,网络层提供的是逐跳(hop-by-hop)协议。
封装
A给B通过网络传送一块数据,可以设想仅仅是传输这块原始数据是不够的,因为网络传输过程中,网络包到了某个路由器,需要转发,而转发必须依赖数据包的一些附加信息,比如目标机器。
发送端在发送数据的时候,将原始数据按照协议格式加上一些控制信息,包装成可在网络上正确传输数据包的过程叫封装。
TCP/IP协议族是层层封装的,从应用层到链路层,每经过一层都要添加一些额外信息(首、尾部)。
- 用户数据经过应用程序加上应用程序首部,转给TCP层处理
- 经过TCP层加上TCP首部,产生TCP段(segment)
- TCP segment经过IP层再加上IP首部,产生IP数据包(datagram)
- IP datagram通过链路层,经以太网驱动程序处理后,加上以太网首部+尾部,产生以太网帧(frame),以太网帧的长度在46~1500之间
更准确的说,在IP和链路层传输的数据单元叫分组(Packet),分组既可以是一个IP datagram也可以是IP datagram的一个分片(fragment)。
UDP的封装跟TCP略有不同,主要体现在经过传输层(UDP)之后添加的是8字节UDP首部,产生UDP datagram。
封装过程中,经过TCP/UDP层的时候,会把端口号添加到TCP/UDP首部;经过IP层的时候,会把协议类型(TCP or UDP or ICMP or IGMP)添加到IP首部;经过链路层的时候,会把帧类型(IP or ARP or RARP)添加到以太网首部。这些信息将被用于接收端的处理。
接收端收到数据后,要执行跟发送端相反的解封操作,我们可以把发送端的数据封装比喻成洗澡后一层层穿衣服,而接收端的操作,类似洗澡前一层层脱衣服,把首尾部剥离,获取传递的原始数据。
因为网络上的主机有不同字节序,现在要通过网络传输,便需要约定统一的网络字节序(大端序),采用小端序的主机在网络传输数据的时候要转为大端序。
地址
互联网上每个接口都有一个唯一的网络地址,也叫IP地址,IP地址有IPv4和IPv6两个版本,IPv4是32位4字节的整数,每个字节(8bit)的取值范围是0~255,所以可以把4字节的IPv4用四个点分隔的byte值表示,比如140.252.13.88,每个十进制数值对应32位整数中的每个字节,这种表示法叫点分十进制表示法,很显然,点分十进制法和int32两种表示法之间很容易相互转换。
IPv4地址划分为ABCDE五类,32位地址表示的数值空间有限,难以为互联网上的所有联网设备分配独立的IP地址,所以便存在动态分配、共享、公网+内网地址转化(NAT)等问题,本质上是为了解决IP地址不够用的问题。
IPv6使用128bit,2的128次方就非常大了,号称可以为地球上每粒沙子分配一个ip地址。
IP数据报(网络层)用IP地址、而以太网帧(链路层)则是用硬件(48位Mac)地址,ARP和RARP用于IP地址和硬件地址之间做映射(转换)。
端口
TCP/UDP采用16位端口号来识别(区分)应用,比如主机A向主机B发送了一个IP报,主机B的内核收到该IP报之后,应该交给哪个应用程序去处理呢?端口号就是用来干这个的,内核会维护端口号到应用程序之间的对应关系。
比较常用的应用层协议有约定的端口号,也就是知名端口号,而1024~5000之间的端口号是分配给TCP/IP临时用的,而大于5000的另做他用。也就是说,你用TCP方式去连网络服务器,本地为该socket分配的端口号会在1024~5000之间,这取决于操作系统的端口分配策略。
域名系统
域名系统(DNS)提供主机名字和IP地址之间的转换,比如www.baidu.com是一个域名,应用程序可以通过一个标准库函数(gethostbyname)来获得给定名字主机的IP地址,标准库函数(gethostbyaddr)实现逆操作。
ip地址是一串数字,含义不清、也不便于记忆,主机名含义更清晰,www.baidu.com你就很容易记住,这也是为什么存在IP地址还需要主机名的原因。
分用
接收端接收到以太网数据帧(Frame)之后,需要像剥洋葱一样,从协议栈由底向上升,即遵照链路层->网络层->传输层->应用层的顺序,去掉各层协议添加的首尾部,将数据取出,交给最上层应用程序,这个过程叫Demultiplexing,尊从书本的翻译叫分用。
回顾前面封装的描述,在传输层、网络层、链路层,分别将端口号存入TCP/IP首部,将协议类型存入IP首部,将帧类型存入以太网帧首部。所以在接收端,将一层层拆掉首部,取出对应信息,然后做分派,丢给不同模块处理,上图就是整个处理过程。
小结
本文讲了地址、域名、端口、TCP/IP分层模型、封装、分用等概念。
你最好能记住TCP/IP链路层->网络层->传输层->应用层的四层划分。
TCP segment、UDP datagram、IP datagram、IP fragment、以太网frame、以及IP层和链路层之间传输的数据单元packet,这些概念你最好分清楚,这样交谈的时候会显得比较专业而不是很土。
数据封装,多看几遍你便能记住了。
- TCP封装格式:以太网首部(14)+IP首部(20)+TCP首部(20)+应用数据+以太网尾部(4)
- UDP封装格式:以太网首部(14)+IP首部(20)+UDP首部(8)+应用数据+以太网尾部(4)
应用层协议在应用层实现,而传输层、网络层、链路层都是在内核实现,所以想修改或者优化底层协议很难,因为你几乎动不了内核,因为网络上的大量设备OS你没法一并改过来,这就是所谓的网络设备僵化问题,HTTP3用UDP替代TCP,就是想在应用层自己去实现可靠传输等。
每个以太网帧有长度限制(48~1500),网络上每个设备也有对包的长度限制,IP报大了就要分片,分片可能发生在发送端,也有可能发生在中间设备,但应该尽量避免分片,IP报会带有信息让分片后可以重组,MTU的概念可以了解一下。
ICMP和IGMP逻辑上属于网络层,因为他们是IP协议的附属协议,但实际上,ICMP和IGMP报文都被封装为IP datagram传输,所以又可以把他们视为IP层之上的协议。
同样ARP和RARP用于IP地址和硬件MAC地址相互转换,逻辑上属于链路层,但实际上arp和rarp报文跟IP datagram一样,都被封装成以太网Frame传输。
接收端收到以太网帧之后,会走分用流程,最终将原始数据交给应用程序。
TCP/IP协议的应用程序经常使用socket编程接口。
有很多跟网络相关的工具,比如ping、ifconfig、netstat、arp、tcpdump、wireshark等。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Impractical Python Projects
Lee Vaughan / No Starch Press / 2018-11 / USD 29.95
Impractical Python Projects picks up where the complete beginner books leave off, expanding on existing concepts and introducing new tools that you’ll use every day. And to keep things interesting, ea......一起来看看 《Impractical Python Projects》 这本书的介绍吧!