计算机网络

计算机网络

计算机网络模型

1.1 OSI参考模型

国际标准化组织(ISO)提出的网络体系结构模型,称为开放系统互联参考模型(OSIRM),通常简称为OSI参考模型

OSI有七层,自下而上依次为物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。其中数据链路层在概念上常被划分为两个子层:逻辑链路控制子层(LLC)和媒体访问控制子层(MAC)。

数据链路层负责分配MAC地址。MAC地址,或称物理地址,由48比特长,12个十六进制数字组成,0~23位(前6位十六进制)是厂商向IETF( 国际互联网工程任务组)等机构申请用来标识厂商的代码。地址的24到47位由厂商自行分派,是各个厂商制造的所有网卡的一个唯一编号。 因此一个
网卡会有一个全球唯一固定的MAC地址,但可对应多个IP地址。MAC地址的第48位是组播地址标志位。

网络层负责对数据包进行路由选择和存储转发,网络层的协议有: IP、IPX、ICMP、IGMP、ARP、RARP、OSPF 等。网络层数据的单位称为分组或数据包。网络层提供点到点的通信(直接相连的结点之间的通信),仅提供一台机器到另一台机器之间的通信,不会涉及程序或进程的概念。

传输层是第一个端到端,即进程到进程的层次。传输层提供应用进程间的逻辑通信。由于一个主机可同时运行多个进程,因此传输层有复用和分用的功能。传输层的协议有: TCP、 UDP、 SCTP 等。传输层数据的单位称为报文或数据段

应用层为操作系统或者网络应用程序提供访问网络服务的接口。应用层的协议有: RIP、TELNET、FTP、HTTP、SNMP等。

OSI参考模型 功能 协议 设备
物理层 中继器、集线器
数据链路层 分配MAC地址 网桥、交换机
网络层 对数据包进行路由选择和存储转发(点到点) IP、IPX、ICMP、IGMP、ARP、RARP、OSPF等 路由器
传输层 提供进程间的逻辑通信(端到端) TCP、 UDP、 SCTP等

网关是网络层以上的中继系统。默认网关在网络层以上实现网络互连,实质上是一个网络通向其他网络的IP地址。

1.2 TCP/IP模型

TCP/IP模型由于得到广泛应用而成为事实上的国际标准,从低到高依次为:网络接口层、网际层、传输层和应用层。

OSI七层模型和TCP/IP五层模型的对应关系如下:

image-20220704093830695

网际层是TCP/IP体系结构的关键部分。它和OSI网络层在功能上非常相似。网际层将分组发往任何网络,并为之独立地选择合适的路由,但它不保证各个分组有序到达,各个分组的有序交付由高层负责。网际层定义了标准的分组格式和协议,即IP协议。当前采用的IP协议是第4版,即IPv4,它的下一-个版本是IPv6。

传输层的功能同样和OSI中的传输层类似,是使发送端和目的端主机上的对等实体可以进行会话

传输层主要使用以下两种协议:

  • 传输控制协议(Transmission Control Protocol, TCP)。 它是面向连接的,数据传输的单位是报文段,能够提供可靠的交付。
  • 用户数据报协议(User Datagram Protocol, UDP)。 它是无连接的,数据传输的单位是用户数据报,不保证提供可靠的交付,只能提供“尽最大努力交付”。

应用层包含所有的高层协议。如虚拟终端协议(Telnet)、 文件传输协议(FTP)、 域名解析服务(DNS)、电子邮件协议(SMTP)和超文本传输协议(HTTP)。

传输层与socket基本操作

2.1 传输层

在下图中,展示了IPv4和IPv6。从右向左观察这个图,最右边的4个网络应用使用IPv6,另外的5个网络应用使用IPv4。

最左边的网络应用tpdump直接使用BPF(BSD分组过滤器)或DLPI(数据链路提供者接口)同数据链路层进行通信。ping使用ICMP协议。

image-20220704094553193

UDP

用户数据报协议(User Datagram Protocol),面向数据报文。UDP是一种无连接协议,因为UDP客户与服务器不必存在长期的关系,例如一个UDP客户创建一个套接字并发送一个数据报给一个服务器,然后立即用同一个套接字发送另一个数据报给另外一个服务器。同样,一个UDP服务器可以用同一个UDP套接字从若干不同的客户一连串接受多个数据报。

UDP是不可靠的,不能保证最终到达它们的目的地,不保证各个数据报的先后顺序跨网络保持不变,也不保证每个数据报只到达一次

UDP既可以使用IPv4,也可以使用IPv6。

TCP

传输控制协议(Transmission Control Protocol),面向字节流

第一,TCP 是一种面向连接的协议,提供客户与服务器的连接。

第二,TCP提供可靠性。当使用TCP向另一端发送数据时,它要求对端返回一个确认。如果没有收到确认,TCP自动重传数据并等待更长时间。在数次重传失败后,TCP才放弃。

第三,TCP通过给所发送数据的每一个字节关联一个序列号进行排序。UDP提供不可靠的数据报传送,不提供确认、序列号、超时重传等机制。

第四,TCP提供流量控制,而UDP不提供流量控制。TCP总是告诉对端它能够接收多少字节的数据,这称为通告窗口。该窗口在任何时刻都指出接收缓冲区中的可用空间,从而确保发送端发送的数据不会溢出接收缓冲区。

第五,TCP的连接是全双工的。UDP也可以是全双工的。

TCP既可以使用IPv4,也可以使用IPv6。

UDP与TCP的主要区别在于UDP不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP在许多方面非常有效,如UDP具有对系统资源要求较少、具有较好的实时性、网络开销小的优点。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定数据的重要性相对较低),可使用UDP。

2.2 TCP连接的建立和终止

以下给出了一个基本TCP客户端和服务器程序的套接口函数:

image-20220704095345763

对于服务器端,其先调用socket函数(返回一个套接字),然后套接字与地址、端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。

这时如果有客户端调用socket函数(返回一个套接字),然后连接服务器(connect),如果连接成功,客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把响应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

image-20220704100516344

三次握手建立连接


  • 客户端向服务器发送一个SYN J;
  • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1;
  • 客户端再向服务器发送一个确认ACK K+1。

image-20220704100639833

从图中可以看出,服务器必须准备好接受外来的连接。这通过socket、bind 和listen函数来完成,称为被动打开

客户端通过调用connect进行主动打开。这引起客户端向服务器发送了SYN J (表示同步,它告诉服务器客户将在连接中发送的数据的初始序列号)分节,这时connect进入阻塞状态。

服务器监听到连接请求,即收到SYN J分节,调用accept函数接受请求,并向客户端发送SYN K (它告诉客户端服务器将在连接中发送的数据的初始序列号)、ACK J+1分节,这时accept进入阻塞状态。

客户端收到服务器的SYN K、ACK J+1 分节之后,这时connect返回,并对SYN K分节进行确认,再向服务器发送ACK K+1分节;

服务器收到ACK K+1分节时,accept 返回,至此三次握手完毕,连接建立。

总结:客户端的connect在三次握手的第二次返回,而服务器端的accept在三次握手的第三次返回。

==TCP为什么不采用二次握手:==

采用三次握手是为了防止失效的连接请求报文段突然又传送到服务器,从而发生错误。

比如,客户端第一次发送的连接请求并没有丢失,而是因为网络问题导致延迟到达服务器,服务器以为是客户端又发起的新连接,于是服务器同意连接,并向客服端发回确认,但是此时客户端处于建立连接的状态,所以不予理会,服务器就一直等待客户端发送数据, 导致服务器的资源浪费。

四次挥手释放连接


==建立连接需要三次握手,而终止连接需要四次挥手。这是由TCP的半关闭造成的。既然TCP连接是全双工的(数据在两个方向可以同时传递),因此每个方向必须单独地进行关闭。==

下图中是客户执行主动关闭,然而不管是客户还是服务器都可以执行主动关闭。通常情况下是客户执行主动关闭,但某些协议如HTTP则是服务器执行主动关闭。

image-20220704101542526

img

具体步骤:

  1. 某个应用进程首先调用close,我们称这一端执行主动关闭。 这一端的TCP于是发送一一个FIN分节,表示数据发送完毕;

  2. 另一端接收到FIN分节之后,执行被动关闭,对这个FIN进行ACK确认。它的接收也作为文件结束符传递给接收端应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据

  3. 一段时间之后,接收到文件结束符的应用进程调用close关闭它的套接口。这导致它的TCP也发送一一个FIN

  4. 接收到这个FIN的原发送端TCP (即执行主动关闭的那一端) 对它进行确认

这样每个方向上都有一个FIN和ACK,所以一共需要四个分节。我们使用限定词“一般”是因为:有时步骤1)的FIN随数据一起发送;另外,执行被动关闭那一端的TCP在步骤2)和3)发出的ACK与FIN也可以合并成一个分节(当自己已经没有数据要发送了,可以直接关闭连接),这样的话就是三个报文完成连接的释放。

TCP关闭时,每一端都要发送一个FIN。这种情况除了在应用进程调用close时会发生,还会在进程终止时发生。进程终止包括自愿(调用exit或从main函数返回)、不自愿(进程收到一个终止本进程的信号)的情况,进程终止时所有打开的TCP连接上都会发出一个FIN。

==TCP释放连接为什么需要四次挥手:==

关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了(单方向),但未必你所有的数据都全部发送给对方了,所以你未必会马上关闭socket,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你没有数据发送给对方了,针对每个FIN报文,都需要一次ack报文,故需要四次挥手。

https://github.com/whuchris/Interview/blob/master/Java/TCP%E5%92%8CUDP%E5%8D%8F%E8%AE%AE.md

握手的过程中可以说没有信息数据的传输,是一个相互应答的过程,所以服务器会将SYN ACK一起发送,但是客户端发送终止连接的时候,很有可能服务器还有一些数据没有发送完,所以服务器只是先答应,但是需要等待数据传输完毕之后再发送FIN报文,ACK和FIN是分开的,因此多了一次。

2.3 TCP状态转换图


TCP连接的建立和终止可以用状态转换图来说明,如图2-5所示。这些状态可使用netstat显示,它是一个在调试客户/服务器应用时很有用的工具。

TCP为一个连接定义了11种状态,并且TCP规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一个状态。举例来说,当某个应用进程在CLOSED状态下执行主动打开时,TCP将发送一个SYN,且新的状态是SYN_ SENT。如果这个TCP接着接收到一个带ACK的SYN,它将发送一个ACK,且新的状态是ESTABLISHED。这个最终状态是绝大多数数据传送发生的状态。

自ESTABLISHED状态引出的两个箭头处理连接的终止。如果某个应用进程在接收到文件结束符之前调用close (主动关闭),那就转换到FIN _WAIT_1状态。但如果某个应用进程在ESTABLISHED状态期间接收到一个FIN (被动关闭),那就转换到CLOSE WAIT状态。

image-20220704104439563

图2-6给出了一个完整的TCP连接所发生的实际分组交换情况:建立连接、传送数据和终止连接。图中展示了每个端点所经历的TCP状态。从图2-6可见,当客户端应用程序主动请求关闭时,调用close或shutdown关闭连接,这时应用程序发送FIN,然后进入FIN_WAIT_1状态,等待服务器端发送确认包ACK,接受到服务器端的ACK以后,然后客户端进入FIN_WAIT_2状态,等待服务器端调用close, 并发送FIN,当客户端接受到FIN后,发送ACK,进入最终的TIME_WAIT状态。

需要注意的是,执行主动关闭的那一端进入==TIME WAIT状态==。留在TIME_ WAIT的持续的时间是==MSL== (最长分节生命周期Maximum Segment Liftime)时间的2倍,也就是2MSL。MSL一般情况下是30秒到2分钟,所以TIME_WAIT的时间一般为1~4分钟。

image-20220704154040857

==存在TIME_WAIT状态有两个理由:==

  • 实现终止TCP全双工连接的可靠性

    假设最终的ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK。如果不维护状态信息,它将响应以RST,而服务器则把该分节解释成一个错误。 如果TCP打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流,那么它必须能够处理连接终止序列四个分节中任何一个分节丢失的情况,也即主动关闭的那一端必须进入TIME_WAIT状态,因为它可能不得不重发最终的ACK。

  • 允许老的重复分节在网络中消逝

    我们假设12.106.32.254端口1500和206.168.112.219端口21之间有一个TCP连接,我们关闭这个连接后,在以后某个时候又重新建立起相同的IP地址和端口之间的TCP连接。后一个连接称为前一个连接的化身,因为它们的IP地址和端口号是相同的,TCP必须防止来自某个连接的老重复分组在连接终止后再现,从而被误解成属于同一个连接的化身(被误解为属于新建的连接)。要实现这种功能,TCP不能给处于TIME_WAIT状态的连接启动新的化身,既然TME_WAIT状态的持续时间是2MSL,这就足够让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃,通过实施这个规则,我们就能保证当成功建立一个 TCP连接时,来自该连接先前的化身的老重复分组都已在网络中消逝了。

2.4 socket的基本操作


一个面向连接的客户端socket程序的主要步骤:

  1. 加载套接字库

  2. 创建套接字socket()

  3. 向服务器发送连接请求connect()

  4. 和服务器端进行通信

  5. 关闭套接字close()

  1. socket()函数

    1
    int socket(int domain, int type, int protocol);

    socket函数在成功时返回一个小的非负整数值,称为套接口描述字(Socket Descriptor), 简称套接字。这个套接字跟文件描述字相似。

    socket函数的三个参数分别为:

    1. domain:即协议域,又称为协议族(family)。常用的协议族有: AF_ INET、 AF_ INET6、AF LOCAL(或称AF_ UNIX,UNIX域socket)、AF_ ROUTE等。协议族决定了套接口的地址类型,在通信中必须采用对应的地址,如AF_ INET决定了要用IPv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

    2. type:指定套接口类型。常用的socket类型有: SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_SEQPACKET等。

    3. protocol:指定协议。常用的协议有: IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP等,它们分别对应TCP传输协议、UDP传输协议、SCTP传输协议。

    注意:上面的type 和protocol 并不是可以随意组合的,如SOCK_ STREAM不可以跟IPPROTO_ UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

  2. bind()函数

    bind函数把一个本地协议地址赋予套接口。对于网际协议,协议地址是32位的IPv4地址或128位的IPv6地址与16位的TCP或UDP端口号的组合。

    1
    int bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen) ;

    函数的三个参数分别为:

    1. sockfd:即套接字,它是通过socket()函数创建的,它唯一标识一个套接口。

    2. addr:一个指向特定于协议的地址结构的指针。

    3. addrlen:指出第二个参数中结构体的长度。

    通常服务器在启动的时候都会绑定一个众所周知的地址(如IP地址+端口号),用于提供服务,客户就可以通过它来连接服务器;而客户端就不用指定,由系统自动分配一个端口号和自身的IP地址组合。**==这就是什么三次握手时为服务器端在listen之前会调用bind,而客户端就不调用,而是在connect时由系统生成一个。==**

  3. listen()函数

    1
    int listen(int sockfd, int backlog)

    listen函数仅由TCP服务器调用,它做两件事情:

    1. 当socket函数创建一个套接口时,它被假设为一个主动套接口,也就是说,它默认是一个将调用connect发起连接的客户套接口。listen函数把一个未连接的套接口转换成一个被动套接口,指示内核应接受指向该套接口的连接请求。调用listen导致套接口从CLOSED状态转换到LISTEN状态。

    2. listen函数的第二个参数backlog规定了内核应该为相应套接口排队的最大连接个数(后台等待连接队列的最大限制值)(包括已完成连接队列与未完成连接队列)。

    • 未完成连接队列。

      每个这样的客户对应其中- -项:客户已经发出建立连接请求,且请求已到达服务器,而服务器正在等待完成相应的TCP三路握手过程(服务器已发出第二个分节,等待客户端的第三个分节)。这些套接字处于SYN_ RCVD状态。

    • 已完成连接队列。

      每个已完成TCP三路握手过程的客户对应其中- -项。这些套接字处于ESTABLISHED状态。

  4. connect()函数

    TCP客户用connect函数来建立与TCP服务器的连接

    1
    int connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    connect函数的第一个参数即为客户端的套接字,第二参数为一个指向套接口地址结构的指针,第三个参数为第二个参数中结构体的长度。

  5. accept()函数

    accept函数由TCP服务器调用。

    1
    int accept (int sockfd, struct sockaddr addr, socklen_t addrlen) ;

    accept函数的第一个参 数为服务器的套接字,第二个参数用于返回客户端的协议地址,第三个参数为协议地址的长度。

    如果accept成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与所返回客户的TCP连接。

  6. close()函数

    close函数用来关闭套接口,并终止TCP连接。

    1
    int close(int fd);

    close一个TCP套接口的默认行为是把该套接口标记为已关闭,然后立即返回到调用进程。该套接字不能再由调用进程使用,也就是说不能再作为read或write的第-一个参数。
    注意:close操作
    只是使相应套接字的引用计数减1
    只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求(激发TCP的正常连接终止序列,即发送FIN))。

  7. shutdown()函数

    关闭一个socket有2种方法,分别是close与shutdown。

    shutdown函数的原型是:

    1
    int shutdown (int sockfd, int howto);

    sockfd是需要关闭的套接口描述字。参数howto允许为shutdown操作选择以下几种方式:

    SHUT_RD:关闭连接的读端。也就是该套接字不再接收数据,任何当前在套接字接收缓冲区的数据将被丢弃,但仍可写。进程将不能对该套接字发出任何读操作。调用之后接收到的任何数据将被确认然后无声丢弃掉。注意此时并不发送FIN。

    SHUT_WR:关闭连接的写端,进程不能再对此套接字发出写操作,但仍可读。对于TCP的套接字(socket), 这称为半关闭,当前留在套接字发送缓冲区中的数据将被发送掉。不管套接字的引用计数是否等于0,关闭写端的操作都会执行,即会发送FIN。

    SHUT_ RDWR:相当于调用shutdown两次:第一次指定howto为SHUT_ RD,第二次指定howto为SHUT_WR。

    ==close和shutdown的区别:==

    • close 会关闭连接,并释放所有连接对应的资源,**套接字不能再由调用进程使用**,即它不能再作为read或write的参数;而 shutdown 并不会释放掉套接字和所有的资源,关闭读仍然可以write,关闭写仍然可以read。
    • close 存在引用计数的概念,调用时把套接字的引用计数减1,仅在该计数变为0时才关闭套接字shutdown 则不管引用计数,直接使得该套接字不可用,如果有别的进程企图使用该套接字,将会受到影响。
    • close 的引用计数导致不一定会发出 FIN 结束报文,而 shutdown 则总是会发出 FIN 结束报文,这在我们打算关闭连接通知对端的时候,是非常重要的。
    • close函数同时终止两个方向的数据传送:读和写。shutdown可以只终止一个方向的数据传送。
  8. TCP的半关闭

    TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭,半关闭是通过调用shutdown函数代替close函数实现的

    图2-7显示了一个半关闭的典型例子。让左方的客户端开始半关闭,当然也可以由另一端开始。开始的两个报文和四次挥手一致,初始端发出FIN,接着是另一端对这个FIN的ACK报文段。但后面就和四次挥手不同,因为接收半关闭的一方仍能发送数据。我们只显示一个数据报文段和一个ACK报文段,但可能发送了许多数据报文段。当收到半关闭的一端在完成它的数据传送后, 将发送一个 FIN
    关闭这个方向的连接,这将传送一个文件结束符给发起这个半关闭的应用进程。当对第二个FIN进行确认后,这个连接便彻底关闭了。

    image-20220704181311157

    终止网络连接的通常方法是调用close 函数。不过==close有两个限制,通常可使用shutdown 函数来避免==。

    • close无法直接终止连接

      close函数把套接字的引用计数减1,仅在该计数变为0时才关闭套接字

      使用shutdown(howto参数为SHUT_RDWR或SHUT_WR时)可以不管引用计数就激发TCP的正常连接终止序列

    • close只能同时终止两个方向的数据传送

      close 函数同时终止数据传送的两个方向:读和写

      但是TCP连接是全双工的,有时候我们需要关闭写但仍然可以继续读,shutdown 函数可以完成此工作。

    ==注意:==

    1. 如果有多个进程共享一个套接字,close 每被调用一次,计数减1,直到计数为0时,也就是所有进程都调用了close, 套接字将被释放。

    2. 在多进程中,如果一个进程调用shutdown(fd, SHUT_ RDWR)后其他的进程将无法利用此套接字进行通信。如果一个进程调用close(sfd)将不会影响到其他进程。

网络层

3.1 IPv4地址及网络地址转换NAT

IPv4

连接在Internet的每台主机/路由器都分配一个32bit的全球唯一的标识符。

IP地址的编码方式有三种:分类的IP地址、子网的划分、CIDR。

  • 分类的IP地址

    传统的IP地址是分类的地址,分为A、B、C、D、E五类。均由网络号和主机号组成,网络号代表主机所连接到的网络,主机号代表该主机或路由器在网络中的地址。

    image-20220705093309767

    其中,存在一些特殊的IP地址用于表示特殊用途,不作为主机IP地址:

    • 主机号全为0表示本网络本身;
    • 主机号全为1表示本网络的广播地址;
    • 127.0.0.1网路保留作为环路自检地址,表示任意主机本身;
    • 32bit全为0,即0.0.0.0表示整个TCP/IP网络;
    • 32bit全为1,即255.255.255.255表示整个TCP/IP网络的广播地址。
  • 子网的划分、CIDR在下一节叙述。

网络地址转换

网络地址转换(NAT)是通过将专用网络地址(比如企业内部网Intranet)转换为公用地址(如互联网Internet),从而对外隐藏了内部管理的IP地址。通过在内部使用非注册的IP地址(私有地址),并将它们转换为一小部分外部注册的IP地址(公有地址),从而减少IP地址注册的费用以及节省IPv4地址空间。

私有IP地址值用于局域网LAN,不用于无线局域网WLAN连接。因此私有IP地址不能直接用于Internet,必须通过网关利用NAT把私有IP地址转换为Intemet中合法的全球IP地址后才能用于Intermet。私有IP地址有效地解决了IP地址不足的问题。

私有IP地址网段如下:

10.0.0.0~10.255.255.255172.16.0.0~172.31.255.255192.168.0.0~192.168.255.255

在因特网中的所有路由器,对目的地址是私有地址的数据报一律不进行转发。 使用NAT时,需要在专用网连接到因特网的路由器上安装NAT软件,NAT路由器至少有一个有效的外部全球地址。普通路由器在转发数据报时不改变其源IP地址和目的IP地址,且路由器工作在网络层,而NAT路由器在转发IP数据报时,一定要更换其IP地址(按路由器中的地址转换表转换源IP地址或目的IP地址)。NAT路由器转发数据报时需要查看和转换传输层的端口,其操作没有严格的层次关系

3.2 子网划分与子网掩码、CIDR

子网划分

各类地址的默认子网掩码:

A类: 255.0.0.0
B类: 255.255.0.0
C类: 255.255.255.0

使用子网划分时的地址格式:

A类网络:8位 + 子网X位 + 主机24-X位
B类网络:16 位 + 子网X位 + 主机16-X位
C类网络:24位 + 子网X位 + 主机8-X位

无分类编址CIDR

分类的IP地址的缺点:

比如一个A类地址对应的是2^24 - 2个IP地址(网络地址和广播地址),这个是个天文数字,一个公司或者组织是无法完全利用这么多IP地址的,就造成了IP地址的浪费。

CIDR是在使用变长度子网掩码的基础上提出的一种消除传统A、B、C类网络划分,并且可以在软件的支持下实现超网构造的一种IP地址的网络划分方法。这样可以大幅度提高IP地址空间的利率,并减小路由表大小,提高路由器的路由转发能力。

无分类编址的做法是将IP分为两部分:

1、网络前缀

网络号对应的是一个网络地址,一个网络可以容纳多个主机,主机的网络号相同。

2、主机号

唯一标识一个主机在一个网络中的id。

怎么区分网络号和主机号呢?

使用斜线记法,即IP地址/网络前缀所占比特数,xx:xx:xx:xx/n
在IP地址后边加入了 /n ,n代表前n位为网络号。

CIDR的主要特点:

  1. 消除了传统的A、B、C类地址以及子网的概念,因而可以更加有效地分配IPv4的地址空间。CIDR使用“网络前缀”概念代替子网络概念。这样IP地址分为两部分:网络前缀、主机号。CIDR使用斜线记法,即IP地址/网络前缀所占比特数。其中,网络前缀所占比特数对应于网络
    的部分,等效于子网掩码中连续1的部分。

  2. 将网络前缀都相同的连续的IP地址组成“CIDR地址块”。一个CIDR地址块可以包括多个A、B、C类地址,这种地址的聚合称为路由聚合,或称为构成超网。路由聚合使得路由表中的一个项目可以表示很多个原来传统分类地址的路由,有利于减少路由之间的路由选择信息的交换,从而提高网络性能。

3.3 ARP、RARP、ICMP

  • ARP

    在实际网络的数据链路上传送数据时,最终必须使用硬件地址MAC。所以需要一种方法来完成IP地址址到MAC地址的映射,这就要用到地址解析协议(Address Resolution Protocol, ARP)。 每台主机(路由器) 上单独地存放一个从IP地址到MAC地址的映射表,称为ARP表。主机和路由器使用地址解析协议APR来动态维护此ARP表。MAC地址转换为IP地址使用RARP协议。

  • ICMP

    为了提高IP数据报成功交付的机会,在网络层使用了网际控制报文协议(Internet Control Message Protocol, ICMP) 来使得主机或路由器可以报告差错和异常情况。
    PING命令工作在应用层,但是直接使用网络层的ICMP协议,而**没有使用传输层的TCP或UDP协议**。

3.4 IPv6

IPv6由128bit构成,通常使用冒号十六进制记法表示IPv6地址,每个16bit的值用四位十六进制值表示,各值之间用冒号分割,如68E6 : 8C64 : FFFFF : 0 : 1180 : 960A : FFFF。该表示方法允许使用零压缩,即一连串连续的零可以为一对冒号所取代,如DE08:0:0:0:0:0:0:B3可以写成DE08::B3;IP 地址0:0:0:0:0:0:118.17.23.1可以写成::118.17.23.1。(这里冒号分割的是16bit,点分割的是8bit)

IPv6所引入的主要变化:

  1. 更大的地址空间。IPv6 将地址从IPv4的32bit增大到了128bit;
  2. 扩展的地址层次结构。
  3. 灵活的首部格式。
  4. 改进的选项。这一特征加快了分组处理速度。
  5. 允许协议继续扩充。
  6. 支持即插即用。
  7. 支持资源的预分配。
  8. 增加了安全性,身份验证和保密验证是IPv6的关键特征。
  9. 分片限制为由源点来完成,是端到端的,路由途中的路由器不允许进行分片。

网络常用测试工具

ping

检查网络是否通畅或者网络的连接速度。

原理:利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通、时延是多少。

tracert

tracert是路由跟踪实用程序,用于确定IP数据包访问目标所采取的路径

tracert 命令用IP生存时间(TTL) 字段ICMP错误消息来确定从一个主机到网络上其他主机的路由。其命令格式如下:

1
tracert[-d] [-h maximum hops] [-j computer-list] [-W timeout] target_name

可以使用tracert命令确定数据包在网络上的停止位置。例如:tracert www.baidu.com则会打印出从当前主机到目的主机所经过的路由地址。

telnet

查看某个端口是否可访问。Telnet协议是TCP/IP协议家族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。

例如可以用telnet测试80端口的Web服务器是否正常工作

输入telnet www .hitsz.edu.cn 80

然后服务器响应:
Trying 219.223.252.3...
Connected to www .hitsz .edu. cn
Escape character is '^] .

然后输入:
GET / HTTP1.1

如果Web服务器正常工作的话,就会返回服务器的响应头,以便你确认服务器的情况。

netstat

netstat是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息

netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。使用格式为:

1
netstat [-a][-e][-n][-o][-P Protocol] [-r] [-s] [Interval]

一般用netstat -an来显示所有连接的端口并用数字表示。