单播

单播,英文原名unicast,简单的来说就是一对一的通信。绝大多数的网络应用程序都是单播,无论是你用浏览器上网,和别人微信聊天,都是一个通信端口点对另一个通信端口点。如果用现实生活中的例子做一个比方,那么给别人写信就是一个单播的通信方式。下面的图里面,红点对绿点就是一对一的单播模式。

 单播,广播和组播  - 图1

广播

广播,英文原名broadcast,简单的来说就是一对所有的通信。这和中文中最朴素的广播的概念相同,我小时候在我的那个小县城里还能听到广播,只要有一个点播放,基本全城都能听到,也不管你愿不愿意听。就如下图所示,红色的端点将自己的消息广播给所有人。

 单播,广播和组播  - 图2

那么广播有什么实际中的作用呢?想象一下如果一方想要取得某种信息却又不知道去哪里才可以获得该信息,那么只能向当前他所能触及的所有主机发出一个消息,祈求获得回答。这种技术在下一节要详细介绍的ARP协议以及后面会作为几个能接触到常见协议之一的DHCP都会有所应用。

因为前面说过网络通信本质上是通过向IP地址和MAC地址发消息来完成的,再回想下MAC链路层那一节所说的,网卡会通过帧头里面的MAC地址来过滤(选择)自己主机包并交给上层,而又说了一个网络里面的所有主机必须能接受广播的包,而很明显广播地址并不是自己的主机地址,那么每个端点是如何能不剔除广播的包的呢? 而为了达到目的并且不破坏整体设计,实现广播也是通过向一个规定好的地址来发送消息。这个地址要分两个部分来说明:

  • 在IP这一个层次,把一个“子网”里面“主机号”全为1的地址规定为广播地址,向这个地址发送消息,这个子网里的所有主机都能接收到这个消息(如果觉得有点模糊了,回忆下上一节的掩码,网络号,子网号和主机号)。比如说一个192.168.10.0的子网里,广播地址就是192.168.10.255。如果向这个地址发送消息,该消息就会被转发到该子网所有的主机。

  • 在链路层,会把FF.FF.FF.FF.FF.FF这样MAC地址写在Dest MAC这个字段里面,而这个地址就是链路层广播地址。从某种角度来说链路层广播和IP层广播地址基本没有太大的联系。

在很多资料中,会把IP这个层次的广播分为四种,分别是受限的,指向网络的,指向子网的,指向所有子网的。不说翻译的名字有多么的拗口和容易混淆,而且这玩意儿我觉得本身并没有这么复杂。在前面介绍IP层次的广播地址的时候我加了两双引号,就是在这个地方用的。这里的四个层次就是把这两个名词的概念扩大化,怎么扩大化呢?

所谓的受限的广播地址就是255.255.255.255,全1,也就是在一个超级大的子网里所有主机号为1的地址。那难道意思是往这个地址发消息,所有因特网上的主机都能收到消息吗?当然不是的,一个组织里是不可能允许这么牛逼的人存在的,所谓受限就是路由器(后面会详细说明路由器到底都干些什么)不会转发此类数据包,所以这种数据包只会出现在本地网络里。

接下来就是面向网络的,想想前面介绍的IP分类,前8个位是网络号,所谓面向网络就是说netid.255.255.255,这里子网稍微缩小了一点。像这种地址发消息,那么所有的该类网络上的主机都能接收到这个数据包。

后面两个就差两个字,其实区别就是到底有没有划分子网,关于子网的概念前面也有提过。如果没有划分子网,那么就是发给子网里面所有的机器,这就是指向子网的广播地址,如果划分了,那么就是指向所有子网的广播地址。本质上说就看有没有二级组织,有的话,信就是给二级组织的,至于二级组织怎么处理,那这里就不管了。

关于链路层广播,后面马上要介绍的ARP协议就是一个非常好的例子。正好提前剧透一点数据包的内容作为一个直观的例子。我涂掉了我手机的MAC地址以防泄露信息,可以看到dest里面填的是全ff。为什么我说链路层的广播地址和IP层基本没有什么太大的联系呢?因为我上面所吐槽的四类广播地址在其链路层基本上都是全ff的MAC地址。

 单播,广播和组播  - 图3

广播有个弊端,就是会产生大量的流量,因为一个广播消息会被在所有局域网/子网内进行传播并且被每个主机所处理。所以在IPv6上已经没有了广播这个概念,而在IPv4,为了解决这个弊端,可以使用组播这个技术。

组播

组播,学名multicast,可以理解为是一种局域网内有边界的广播形式。最常见的形态就是在一个组播组里面,所有的主机既可以进行多对多通信,也可以进行一对多通信。直观的比喻的话就像微信见一个群聊天,你说一句话整个群里面的人都能知道,但是没有在这个群里面的人是不会收到这个消息的。就像下面这个图里所展示的,红色的和绿色的点是一个组播组里面的,他们发送的消息都能互相看到,而黄色的点不属于该组播组,是无法收到他们看到的消息的。

 单播,广播和组播  - 图4

那么对于一个计算机来说,如何才能找到群名,加入一个“组播组”呢?在"IP地址”这一节有一个IP分类的表,里面有个D类地址,网络号的前缀是1110,这类地址全部用来做组播组的群名。后面第二章介绍网络编程的时候专门会介绍如何使用socket加入组播组。在这里只要能理解,只要所有的主机都加入了同一个以1110开始的地址,或者说都往这个同一个1110开始的地址发消息,那么所有主机都能进行群内通信了。 但是为了实现一些高层次的组播技术,一部分D类地址是作为保留地址用于规定的用途。具体来说就是224.0.0.0~224.0.0.255这个范围内的一般情况下是不要去使用的。而剩下的224.0.1.0~239.255.255.255又被分为了两类,具体如下:

  • 预留组播地址:224.0.1.0~238.255.255.255,用于全球范围或网络协议
  • 管理权限地址:239.0.0.0~239.255.255.255,组织内部使用,用于限制组播范围
    类似于广播,上面描述的是IP层次的组播,因为组播地址从某种角度是上是虚拟的,也就是说并没有真的有个主机是带有224~239的IP地址的。而网络上发送的帧本质上是通过MAC地址来标识目的地的,那么组播地址该映射成什么样的MAC地址呢?答案是这样的:

对于一个组播的MAC地址,前24bit固定为0x01005e,加上第25个bit是0,换句话说,前25个bit是个固定值。这样就可以作为张艺红标记,接口卡和驱动读到这样的MAC地址时就知道这是一个组播帧。剩下的23bit就是组播地址的低23bit。而上面说过组播地址IP的前4bit都是固定的,也就是1110,而后面的28个bit只有后23个bit会被映射到MAC地址,这样会造成一个完整的组播IP地址会有5个bit在转换成为MAC地址时丢失。从而会导致一个现象,就是有可能两个不同的组播地址映射成为的MAC地址时一样的。那么这些冲突的数据包怎么办呢?这就又一次的体现出分层的好处了,这种冲突的数据包只能通过上层进行过滤了。对于这种转换,举个例子就很清晰了:

假设一个组播IP地址224.0.1.2吧,转换成二进制就是1110 0000 0000 0000 0000 0001 0000 0010,这样去取出后23个bit然后加上0x01005e家还是那个一bit的0就是MAC地址了,由于二进制太长了,所以结果用16进制表示就是01:00:5e:00:01:02。

组播的用处很大,虽然说不常能接触到,有幸我曾经工作中就做过一个很好的应用。故事是这样的,有一个服务器,若干个客户机,如何让客户机自动检测到而服务器地址而省去用户配置的步骤?组播就可以在这里用起来了,定义一个组播地址,然后让服务器和主机都加入这个组播组,加入组播组之后,他们互相之间发的消息就可以被对方获知了,那么也就可以自动获取到服务器的地址了。