Visual C++网络编程(txt+pdf+epub+mobi电子书下载)


发布时间:2020-05-26 07:22:17

点击下载

作者:唐文超

出版社:清华大学出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Visual C++网络编程

Visual C++网络编程试读:

前言

互联网已成为人们生活的一部分,各种网络应用层出不穷。社会对网络应用的需求越来越大,对网络应用开发人员的需求也越来越大。如何让开发人员快速掌握网络开发技术,以及打下扎实的网络开发基础?本书正是出于这个目的编写的。

本书从基础知识开始讲解,每一章内容环环相扣,引领读者逐步掌握Windows网络编程的原理和方法。作者有多年的开发经验,本书也正是以一个开发者的角度,结合作者的经验总结,筛选出必要的知识点,使读者能够快速入门的同时又不会遗漏重要的知识。网络应用技术日新月异,本书并不介绍琳琅满目的各种应用,而是着眼于核心基础知识,结合作者自身开发过程中对所碰到问题的总结,必将为读者打下坚实的基础。当然,本书也适时给出实际的例子,让读者能够对所学内容进行消化巩固。

本书内容

本书共13章,逻辑上分为三个部分。第一部分主要讲述TCP/IP协议,由第1~6章组成;第二部分主要讲解Winsock编程,是本书的重点内容,由第7~11章组成;第三部分主要介绍了网络加密及OpenSSL编程,由第12~13章组成。

第一部分:第1章概括地介绍了业界的网络分层模型标准OSI;第2章讨论了几种基础的网络设备,包括集线器、交换机、桥、路由器。这两章为接下来的四章提供了必要的术语和背景知识;第3~5章详细地介绍了TCP/IP网络最基础,也是最重要的组成协议,分别是IP、UDP和TCP;第6章介绍了网络地址转换技术,即NAT。

第二部分:第7章介绍了Winsock编程的基本知识;第8~10章则详细讨论了Winsock的各种I/O模型,包括阻塞I/O模型、select模型、WSAAsyncSelect模型、WSAEventSelect模型、异步I/O事件通告模型、异步I/O回调通告模型,以及IOCP,即异步I/O完成端口通告模型;第11章讨论了Winsock服务提供者(SPI),Winsock SPI位于Winsock API的下层,为Winsock API提供服务,因此,学习Winsock SPI有助于加深对Winsock编程的理解。

第三部分:网络编程离不开网络安全,而加密技术是网络安全最重要的领域之一,因此,本书在第12章介绍了网络加密的基础知识,包括对称和非对称加密的基本原理,数字签名、数字证书以及CA等;同时第12章还介绍了SSL/TLS的基本原理,并介绍了如何使用开源库OpenSSL来创建CA和数字证书。掌握了第12章的基础知识后,第13章则介绍了如何使用OpenSSL来编写网络程序。

本书特色

本书在讲述网络编程的时候,都配备了完整的并且经过严格调试的样例程序,这些样例程序可以从网上下载。同时,在程序中也给出了详细的注释,以便读者能够更好地理解代码的作用。

本书没有使用带有过多业务逻辑的应用程序,如聊天程序、邮件发送程序等,因为这些业务逻辑往往会影响读者对程序结构的理解。相反,本书使用了最简单的业务逻辑,样例程序着重于网络编程本身。如本书在第8~10章介绍各种Winsock I/O模型时,都使用了最简单的回显程序,读者将会看到,即使是同一个回显程序,在使用不同I/O模型时,程序的实现和复杂度将完全不同。笔者相信,要编写高质量的Winsock网络程序,必须要有扎实的网络编程基础知识,并且能够对各种Winsock I/O模型有充分的理解,本书样例程序的目的正在于此:让读者不被过多的业务逻辑干扰,而是能够快速地把握网络程序的本质。

阅读建议

本书建议的阅读顺序是从头到尾逐章阅读,但是由于网络协议部分可能会枯燥无味,如果读者没有耐心阅读详细的网络协议,则可以从第7章网络编程部分开始学习,在阅读网络编程章节的时候,可以回过头去参考第1~6章的内容,这样在了解网络编程的同时,也可以熟悉网络协议。

读者交互

本书代码下载地址为:http://pan.baidu.com/share/link?shareid=494586&uk=3056331768。如果读者对本书有什么意见和建议,或者对图书内容和代码有疑问,请联系作者技术支持邮箱:35047856@qq.com。

代码下载如果有问题,请联系电子邮箱:booksaga@163.com,邮件标题“求VC网络编程代码”,必回复。编 者2013年3月  第1章网络分层模型从本章节可以学习到:● OSI模型● TCP/IP模型

在学习网络编程之前,为了更好地理解网络通信的协议,我们在本章中先来回顾一下目前存在的两种网络分层模型:OSI模型和TCP/IP模型。OSI模型一共分为七层,TCP/IP模型和OSI模型类似,但是只分为四层。本章将分别为读者简单介绍这两种模型,以及它们之间的关系。1.1 OSI模型

OSI的全称是Open Systems Interconnection,即开放系统互联,它由ISO(International Organization for Standardization)制定。OSI是网络通信的一种通用框架,它分为七层,并且定义了在每一层上数据的处理方法。当我们谈到网络协议或者网络硬件时,往往会把这些协议和硬件归结到OSI的某一层上去,如第二层的交换机,又或者第三层的路由器等。所以我们有必要先熟悉一下OSI的七层结构,它从最低层到最高层分别为物理层、数据链路层、网络层、传输层、会话层、表示层以及应用层,如图1-1所示。图1-1 OSI七层模型

读者初次接触OSI模型时可能会比较难记忆,因为它有七层之多。英文里面有一种有趣的记忆方法,根据首字母来造句:All People Seem To Need Data Processing,即所有人好像都需要数据处理,当然,读者也可以发挥自己的想象来加深记忆。注意图1-1中的数字是由下向上计数的,即第一层是物理层,第七层才是应用层。很多资料中提到OSI的层时并不会给出具体名称,而只是给出数字,即第三层、第五层等。接下来的各小节将分别介绍OSI模型每一层的含义以及每一层上常用的协议。1.1.1 第七层——应用层(Application)

顾名思义,应用层是和“应用”相关的。很多协议工作在应用层,目的是为了给应用程序提供服务。注意这里的“应用”要和应用程序相区别。举个例子,当用户使用IE来访问www.google.com的时候,IE是应用程序,这个IE应用程序(或者其他浏览器)为了能够显示google的网页,就需要用到应用层提供的服务,或者更准确地说,需要使用应用层协议提供的服务。首先,IE利用DNS提供的域名解析服务,来获取域名www.google.com的IP地址,如74.125.71.104,然后再通过另外一个协议HTTP,来下载页面内容。在这个过程中出现的两个协议(DNS和HTTP)都是工作在应用层上的协议,浏览器程序(IE)正是使用了这两个协议所提供的服务才能打开页面。

应用层还包括很多其他的应用协议,下面列出一些常用的协议。● FTP:文件传输协议,用来在客户机和FTP服务器之间传输文件。● DHCP:动态主机配置协议,DHCP服务器为客户机动态分配IP

地址。● POP3:邮件接收协议,用于从POP3服务器接收邮件。● SMTP:邮件发送协议,用户通过SMTP服务器发送邮件。1.1.2 第六层——表示层(Presentation)

这里的“表示”是指数据的表示。互联网是一个非常复杂的系统,接入互联网的设备通常使用不同的硬件和操作系统,这些不同的系统之间往往不能直接通信,因为它们可能会使用不同的格式来表示数据,如使用不同的字符集,或者使用不同的字节序(Big Endian和Little Endian)。表示层的工作就是处理这些差异,并且隐藏这些细节,使得这些差异和细节对于第七层应用层来说成为透明,即应用层不需要关心这些细节,这个就是表示层的转换功能(Translation)。

当然,除了转换功能外,表示层的工作还包括压缩(Compression)和加密(Encryption)。压缩能够有效地降低带宽,加密则能够有效地保护信息安全。工作在表示层的加密协议最常用的是SSL(Secure Sockets Layer)。当然加密协议并不一定需要工作在表示层,如IPSec(Internet Protocol Security,因特网协议安全)就工作在第三层网络层中。1.1.3 第五层——会话层(Session)

可以把“会话”理解为两个应用程序进程之间的一个逻辑连接,两个应用程序通过这个逻辑连接在一段时间内交换数据。会话层的作用就是为创建、管理和终止会话提供必要的方法。这些方法一般以API(Application Program Interface,应用程序编程接口)的形式出现。常用的API有NetBIOS(Network Basic Input/Output System,网络基本输入/输出系统)、RPC(Remote Procedure Call,远程过程调用),以及本书将要介绍的Socket API(套接字编程接口)。

会话层还负责管理和确定传输模式。计算机可以有三种模式来传输数据:单向(Simplex)、Half-Duplex(半双工)、Full-Duplex(全双工)。● 单向(Simplex):数据只可以单向传输。● Half-Duplex(半双工):允许数据双向传输,但是一个时刻只能

有一个方向传输,不能同时双向传输。● Full-Duplex(全双工):数据可以同时双向传输。1.1.4 第四层——传输层(Transport)

传输层提供数据传输的服务。要正确理解传输层的含义,需要首先理解“传输”在这里的含义,这里的“传输”指的是端对端(End-to-End)或者主机对主机(Host-to-Host)的传输。要把数据从一个机器传到另外一个机器,中间可能会经历很多网络和设备,但是传输层并不关心中间的传输过程,而是只关心源端和目标端的传输。比如作者要用自己的笔记本打开google,那么和传输层相关的设备只有作者的笔记本和google的一台服务器。正是由于传输层提供了这种端对端的服务,使得应用程序能够直接和目标设备打交道,而无须关心它们之间的通信细节,如中间经过了什么路由器。这就好比传输层为源和目标建立了一条逻辑通道,源端和目标端上的应用程序能够通过这条逻辑通道直接进行数据交互。

传输层上最重要的两个协议是TCP和UDP。TCP是面向连接的协议(Connection-Oriented),UDP是无连接的协议(Connection-Less)。

1. TCP(Transmission Control Protocol,传输控制协议)

TCP在传输数据之前必须先建立一个连接。TCP做了很多工作来提供可靠的数据传输,包括建立、管理和终止连接,确认和重传。同时TCP还提供分段和重组,流量控制(Flow Control)等。

2. UDP(User Datagram Protocol,用户数据报协议)

UDP是一种简单的传输层协议,所以它并不能够提供可靠的数据传输。简单地说,UDP只是把应用程序发给它的数据打包成一个UDP数据报(UDP Datagram),然后再把这个数据报传给IP。需要注意的是,TCP会把应用程序发来的数据根据需要分成若干个大小合适的TCP段(TCP Segment),而UDP却只是简单地把所有发送来的数据打包成一个UDP数据报,所以我们在编写使用UDP的程序时,不能一次性向UDP写入太多数据,否则可能会导致IP分段的后果。

由于可能有很多应用程序同时在使用TCP/UDP,它们都会把数据交给TCP/UDP,而TCP/UDP也会接收来自IP的、包含指向不同应用程序的数据,所以就需要有一种方法来区别(标识)应用程序,这种方法就是通过端口号(Port)来进行多路复用或多路分解。端口号是一个16位的二进制整数,其取值范围是0~65 535。

1. 多路复用(Multiplexing)

多路复用是指当应用程序把数据交给TCP或UDP时,TCP会把这些数据分成若干个TCP段,UDP则会产生一个UDP数据报。在这些TCP段和UDP数据报中,会填入应用程序指定的源端口号和目标端口号,源端口号用于标识发送的应用程序(进程),目标端口号用于指明在目标机器上应该接收数据的目标应用程序(进程)。

2. 多路分解(Demultiplexing)

多路分解是多路复用的逆过程。当在目标机器上的TCP或者UDP接收到TCP段和UDP数据报时,会检查它们的目标端口号,然后根据不同的目标端口号把数据分发给不同的应用程序(进程)。1.1.5 第三层——网络层(Network)

网络层主要关心的是如何把数据从一个设备发送到另外一个设备,另外一个设备有可能在本地网络或者在一个很远的网络中。从这个最基本和最原始的动机出发,我们可以来分析一下网络层需要哪些功能才能够实现这个目标。

首先,要把数据发送到另外一个设备,我们需要知道设备的地址,就好比寄信,没有地址又谈何寄信呢?所以网络层要提供一种地址的方案,以便用来标识在网络上的任何一个设备。其次,有了地址之后,还需要知道如何才能到达指定的地址。比如小明的家在广东某市某镇某街某号,如果有朋友来看望小明的话,他是先坐飞机到广州,然后再转乘大巴,还是先坐火车,中间经过几个省到达广州,然后再转乘大巴呢?很明显,网络层还应该提供一种如何到达指定地址的方案,这就是网络层的路由功能。再者,一个数据报从一个设备到达另外一个设备,中间可能经过了很多不同的网络,每一个网络都有它自己的特征,它们传输数据的能力也不尽相同,有的支持小的数据报,有的支持大的数据报,所以网络层还应该提供一种方案,使得当数据报大于某个网络的传输能力时,能够把数据报拆分为若干个小的数据报,这样这些小的数据报就能顺利通过这个网络。这就是网络层提供的分段(Fragmentation)和重组(Reassembly)功能。

由上面的分析不难看出,为了能够把数据从一个设备发送到另外一个设备,网络层需要提供三个最基本的功能,即地址、路由、分段和重组,当然,还需要一些附加的功能,比如错误处理和诊断。网络层上最重要的协议IP(Internet Protocol),就是为了这些功能而设计的。目前IP一共有两个版本:IPv4和IPv6。两者最主要的区别是使用了不同位数的二进制整数作为地址:IPv4使用32位二进制地址,IPv6使用128位二进制地址。IPv4地址的表示方法一般为用点隔开的4个数字,每个数字的取值范围是0~255,即一个字节大小,如192.168.1.1。IPv6的表示方法一般为用冒号隔开的8个字(word,16位二进制),每个字都用十六进制来表示,如2012:0000:4528:7D76:3C2B:05AD:3F57:1C98。

当然,除了IP外,网络层还包括其他协议,下面列出一些常用的网络层协议。● IGMP(Internet Group Management Protocol,因特网组管理协

议):用于组播(Multicasting),即发送一个UDP数据报给多个

设备。● ICMP(Internet Control Message Protocol,因特网控制报文协

议):IP使用ICMP来交换错误信息或者其他重要的信息。很多工

具都是利用了ICMP来实现其功能,比如Ping、PathPing和

TraceRt等。● IPSec(Internet Protocol Security,因特网协议安全性):通过加

密来保护数据安全,同时IPSec还带有验证功能(Authentication),通过验证来确保计算机只和那些已知的设备

打交道。● RIP和RIPv2(Routing Information Protocol,路由信息协议):路

由器之间通过RIP进行信息交换和共享。● OSPF(Open Shortest Path First,开放式最短路径优先):是路

由器交换和共享信息的另外一个路由协议。1.1.6 第二层——数据链路层(Data Link)

在讲解第三层网络层的时候提到过,网络层关心的是如何把数据从一个设备发送到另外一个设备,这另外一个设备有可能在本地网络或者在一个很远的网络中。数据链路层关心的则是如何把数据发送到本地网络上去。我们平时常说的LAN(Local Area Network,局域网)技术,如以太网(Ethernet)、令牌环网(Token Ring)、光纤分布数据接口(FDDI)和802.11(Wi-Fi)都定义在这一层。

数据链路层又分为两个子层:逻辑链路控制层和介质访问控制层。

1. 逻辑链路控制(Logical Link Control)IEEE 802.2

LLC是由IEEE 802.2定义的,它直接和第三层网络层打交道,对第三层协议进行多路复用和多路分解,如当链路层接收到一个以太网帧(Frame)的时候,它会检查其头部中的EtherType字段,来决定到底应该把数据分发到哪一个第三层协议,如IP还是IPX。对于IP,EtherType字段的值是0x0800;对于IPX,EtherType的值是0x8137。另外LLC还提供错误控制和流量控制。

2. 介质访问控制(Media Access Control)IEEE 802.3

MAC是指对网络介质访问的控制。由于网络介质往往被共享,如一根电缆,那么当同时有多个设备用它来传输数据的时候,就有可能发生冲突。IEEE 802.3定义了CSMA/CD(Carrier Sense Multiple Access/Collision Detection),即载波监听多路访问/冲突检测,来处理数据冲突。

数据链路层还有一个重要的概念,即MAC地址,也有人称其为物理地址、硬件地址、以太网地址等。每一个网卡(Network Interface Card)都有一个唯一的MAC地址,数据链路层协议通过MAC地址来确保数据能够被正确地发送到目标设备。MAC地址是一个48位二进制整数,通常的表示方法是用-隔开的6个十六进制数字,如14-FE-B5-B0-2B-96。1.1.7 第一层——物理层(Physical)

物理层位于OSI的最底层,所有其他层的数据最终都必须经由物理层才能发送出去。物理层的功能包括:● 硬件规范的定义,如电缆、连接器、无线接收器等的工作方式,

网卡、集线器(Hub)等网络设备也工作在物理层。● 编码和信号,物理层把计算机中的二进制0和1转换成可以在物

理介质上传输的信号。● 在把数据转换成信号后(如对于双绞线电缆则是电子脉冲信

号),物理层负责信号的实际发送和接收。1.2 TCP/IP模型

TCP/IP模型分为四层:应用层、传输层、互联网层和网络接口层,如图1-2所示。图1-2 TCP/IP模型的分层

一般来说,人们都把OSI模型和TCP/IP模型对应起来,如图1-3所示。图1-3 OSI模型和TCP/IP模型的关系

值得注意的是,在TCP/IP模型中并不包含物理层(Physical)。另外,两个重要协议ARP(Address Resolution Protocol,地址解析协议)和RARP(Reverse Address Resolution Protocol,反向地址转换协议),在OSI模型中一般被认为是位于第二层数据链路层和第三层网络层之间,而在TCP/IP模型中则位于网络接口层。1.3 本章小结

本章主要讲述了OSI的七层模型以及它与TCP/IP的四层模型之间的关系。发送方应用程序的数据总是从最上层开始,层层向下,最终经由物理层发送出去;相应的,在接收方的物理层接收到数据后,层层向上,最终经由应用层分发到具体的应用程序进程中。在数据层层向下的过程中,每一层都会对数据进行一些封装处理(如打包或者编码);而在数据层层向上的过程中,每一层都会对数据进行一些逆处理(如解包或者解码)。这些对数据的处理和逆处理过程就是为了实现该层的服务。图1-4列出了OSI各层对数据封装处理后所形成的结果以及其常用名称。图1-4 OSI各层对数据封装处理后所形成的结果以及其常用名称

图1-4中第二列给出了用户数据经OSI每一层封装处理后的结果。第三列给出的则是封装结果的常用名称(单位)。从最后一列可以看到,所谓的封装处理就是给数据加入头部或者尾部,或者对数据进行编码。  第2章网络设备从本章节可以学习到:● 网络设备概述● 集线器(Hub)● 交换机(Switch)● 桥(Bridge)● 路由器(Router)2.1 网络设备概述

在第1章讲述OSI的七层模型的时候,主要讲解了每一层上的协议,很少提到各层上的硬件网络设备。虽然本书主要探讨的是Windows Socket编程,并且在一般的编程中并不需要关心网络设备(这也是分层的目的,应用程序不需要理会底层细节),但是如果能够对常用的网络设备和简单网络结构有基本的认识,那么将能更深入地理解网络编程,并且能够更好地对程序进行调试、排错。本章的目的正是在于此,我们将在本章逐一介绍各种主要的网络设备,包括集线器(Hub)、交换机(Switch)、桥(Bridge)以及路由器(Router),同时也会接触到一些由这些网络设备所构成的简单网络结构。2.1.1 数据传输类型

大部分网络设备都是用来传输数据的,所以在学习网络设备之前,有必要先学习一下数据传输。数据传输类型一共分为三类:单播、组播和广播。

1. 单播(Unicast)

顾名思义,单播就是把数据传输到单个目标,即一对一的关系,如图2-1所示。图2-1 单播示例

2. 组播(Multicast)

组播就是把数据传输到多个目标,即一对多的关系,如图2-2所示。图2-2 组播示例

3. 广播(Broadcast)

广播就是把数据传输到某个范围内的所有目标,即一对所有的关系,如图2-3所示。图2-3 广播示例

需要提出的是,按照广播的定义,发送方也属于某个范围内所有目标之一,虽然在图2-3中并没有标明,但是发送方自己也会接受到广播数据。所有TCP/IP的实现都会包含一个loopback接口,广播数据也是通过loopback接口接收的,我们将在后面的章节来讲解它。2.1.2 广播域和冲突域

我们在上一节提到了数据传输的三种方式,在介绍广播的时候,或许你会发现笔者使用了一个很模糊的词,“某个范围内”,其实这个范围就是本小节所要讲述的广播域。

1. 广播域(Broadcast Domain)

所谓广播域,是指在一个网络中能够相互接收广播数据的一组设备。也就是说,如果一个设备发送广播数据,那么在其广播域内所有其他设备都能接收到。

2. 冲突域(Collision Domain)

这里的“冲突”是指数据在传输的时候发生冲突,即在某个网络环境里,如果两台设备同时发送数据,那么就有可能发生冲突,换句话说,在任一时候,只能有一台设备在发送数据。冲突域就是指在某个网络环境里会发生冲突的一组设备。很明显,冲突并不是一件好事,因为一旦发送冲突,两个冲突的设备都需要重新发送数据,如果在一个网络里频繁发生冲突,那么整个网络的性能就会大打折扣。还记得我们在第1章谈论数据链路层的时候,提到过CSMA/CD吗?翻译过来就是载波监听多路访问/冲突检测,很明显,这个技术就是用来处理数据冲突的。冲突域是一个很重要的概念,我们在下面讲解交换机时还会继续进行讨论。2.2 集线器(Hub)

集线器是工作在第一层(物理层)上的网络设备。集线器是很简单的设备,其作用就是把几台设备连接起来,使它们之间能够进行通信。集线器有若干个接口,每一个接口可以连接一个设备,如图2-4所示。图2-4 由集线器连接起来的4台设备

由图2-4可以看出,由主机A发出的数据,另外三台主机B、C和D都可以接收到,这也是集线器的特点,即它会把从一个接口接收到的数据简单地转发到所有其他接口。这里细心的读者可能会注意到,这不是三种数据传输类型里面的广播吗?我想要单播怎么办?或者说如果我想要A的数据仅发送到C,那么集线器岂不是做不到?是的,集线器因为它的工作特点是做不到,但是单播和组播还是可以实现的,答案就在于网卡。在第1章谈到数据链路层的时候提到过MAC地址的概念,每个网卡都有一个唯一的MAC地址,第二层(数据链路层)在封装数据的时候会在数据帧中填入目标设备的MAC地址。比如我想要A的数据仅发送到C,那么数据帧中目标MAC地址就是C的MAC地址,虽然集线器把这个帧同时发给了B和D,但是因为B和D的网卡的MAC地址和帧的目标MAC地址不一致,所以B和D会直接忽略掉这个帧,这样就实现了单播。

由图2-4还可以看出,如果A和B同时往C发送数据,那么数据肯定会发送冲突,所以通过集线器直接相连的所有设备都处于同一个冲突域里面。同样很明显的是,如果A发出广播数据,那么B、C和D都能接收到广播数据,所以通过集线器直接相连的所有设备都处于同一个广播域里面。2.3 交换机(Switch)

交换机和集线器的不同之处在于,所有和交换机直接相连的设备都被交换机隔离在不同的冲突域里面,也就是说,如果两台设备同时发送数据,那么将不会有冲突。要理解为什么交换机能够把连接的设备隔离在不同的冲突域,需要知道交换机的特点。一般的交换机工作在OSI的第二层,更加高级的交换机则可以工作在第二层或者第三层。这里我们着重来了解第二层交换机的工作方式。

交换机有若干个接口,每一个接口可以连接一个设备,如图2-5所示。图2-5 由交换机连接起来的4台设备

由于交换机工作在第二层,所以比集线器更加智能,至少交换机可以检查出经过它的数据帧所包含的源和目标MAC地址,正是因为有了这种能力,交换机才可以把它的接口和连接该接口的设备关联起来。如图2-5所示,当设备A向C发送数据的时候,假设A连接的是交换机的接口1,C连接的是交换机的接口3,那么当交换机的接口1收到来自A的数据帧的时候,交换机会检查数据帧的源MAC地址,发现是A,所以交换机就把接口1和A关联了起来。同理,交换机可以根据经过它的数据帧的源MAC地址来确定任意接口所连接的设备。现在假设交换机已经知道了接口1对应A,接口3对应C,所以当A向C发送数据的时候,交换机就知道应该把数据转发到接口3,即C,而不会像集线器那样,把数据同时转发到B和D。

现在假设在A(接口1)向C(接口3)发送数据的同时,B(接口2)也向D(接口4)发送数据,如果使用的是集线器,我们知道将会发生冲突,因为无论是来自A还是B的数据都会同时被转发到其他所有接口。然而如果使用的是交换机,它会把来自A的数据转发到接口3,来自B的数据转发到接口4,很明显,没有冲突发生。

可能你会问,如果A和B同时往C发送数据呢?会有冲突吗?答案在于交换机的内部实现。交换机通常都会设置一个内部缓冲区,当交换机发现A和B同时向C发送一个数据帧的时候,它“知道”如果同时把这两个数据帧都转发到C,将会有冲突,所以它会把其中一个帧缓存起来,然后把另外一个帧先发送出去,待完全发送完毕后,再把缓存的帧也发送出去,这样就避免了冲突。如果A向B发送数据的同时,B也向A发送呢?同样可以应用缓冲区来实现。

通过上面的分析可以看到,交换机通过接口关联MAC地址和缓存技术,实现了为直接相连的设备创建相互独立的冲突域。我们也能看到,交换机之所以能够做到这点,是因为它是工作在第二层的,所以它具备足够的智能来实现这个功能。而对于第一层的集线器,很明显它不具备这样的能力,但是因为集线器工作在第一层,它也不需要具备这样的能力。

对于广播,交换机的设计是转发广播帧,所以所有和交换机直接相连的设备都在同一个广播域里。2.4 桥(Bridge)

桥和二层交换机一样,也是工作在OSI的第二层。桥和二层交换机非常相似,因为它也能把接口和与该接口相连接的设备的MAC地址关联起来,所以桥的每一个接口都可以建立一个独立的冲突域。同样的,桥并不划分广播域,即所有与桥直接相连的设备都在同一个广播域里。但是桥和二层交换机也有区别,一般来说,桥是用于连接网段(Network Segment)的,而交换机则用于连接设备。

如图2-6所示,多个设备通过集线器连接成一个网段,然后这个集线器再和桥连接。也就是说,桥的一个接口会连接多台设备。图2-6 由桥连接起来的两个网段

在图2-6中,由于桥和集线器的特性,所以一共有两个冲突域,一个广播域。具体地说,桥把两个通过集线器连接的网段划分成两个冲突域,而由于桥和集线器都不划分广播域,所以图2-6中的5台主机都在同一个广播域里。2.5 路由器(Router)

路由器是工作在OSI第三层(网络层)的设备。我们在第1章介绍第三层的时候说过,网络层主要关心的是如何把数据从一个设备发送到另外一个设备,这另外一个设备有可能在本地网络或者在一个很远的网络中。为了实现这个目标,网络层需要提供三个最基本的功能,即地址、路由、分段和重组,IP协议就是为了实现这些功能而设计的协议,而在这里谈到的路由器,就是为了实现这些功能而设计的网络设备。

简单地说,路由器是用来在网络或者子网(Subnet)间转发数据包(Packet,请参看图1-4)的。注意:路由器连接的是子网,而交换机或者集线器连接的则是在子网里的设备,如图2-7所示。图2-7 通过路由器连接起来的两个子网

先来看看路由器与广播域、冲突域的关系。路由器不同于前面提到的集线器、交换机和桥,路由器既划分冲突域,也划分广播域。你能看出图2-7中一共有多少个冲突域和多少个广播域吗?首先来看广播域,由于只有路由器划分广播域,所以图2-7中有两个广播域,一个是子网A,另外一个是子网B。现在来看冲突域,由于路由器和交换机都划分冲突域,所以图2-7中一共有4个冲突域:在子网A中交换机连接着两台计算机,这样就形成了两个冲突域,另外交换机和路由器的连接构成了第3个冲突域,最后,子网B以及其和路由器的连接构成了第4个冲突域。

现在来看看路由器的主要功能,即路由(Routing)。想要理解路由器的路由最好通过一个例子,如图2-8所示。图2-8 主机192.168.1.2往另外一个子网中的主机192.168.2.8发送一个数据包

要理解图2-8所示的例子,首先要对一些基本概念有一定的了解,如IP地址、子网,以及默认网关(Default Gateway)等。

1. IPv4地址

在第1章介绍第三层网络层时提到过IP地址,现在再来简要介绍一下IP地址和子网(我们将在后面的章节详细讨论)。IPv4地址的一般形式为a.b.c.d,其中a、b、c和d的取值范围都是0~255,也就是一个8位二进制。一个IPv4地址可以分为两部分:网络ID和主机ID。由于历史的原因,现在一共有三种划分IPv4地址的方法,如下所示。● 第一种也是最早、最简单的一种划分方法称为分类法(Classful

Addresssing),即把IPv4地址分为A、B、C、D和E五类。A类地

址把IPv4地址的4个字节中的第一个字节作为网络ID,剩下的三

个字节作为主机ID;B类地址把前两个字节作为网络ID,剩下的

两个字节作为主机ID;C类地址把前三个字节作为网络ID,剩下

的一个字节作为主机ID。D类地址是用于组播的;E类地址则作

为预留地址。如192.168.2.1就是一个C类地址,前面三个字节“192.168.2”就是网络ID,最后一个字节“1”就是主机ID。● 第二种称为子网化(Subnetting),即在分类法(第一种)的基

础上,从主机ID中取出前面若干位来作为子网ID(Subnet ID)。● 第三种,也是目前正在使用的一种划分方法,称为

CIDR(Classless Inter-Domain Routing),中文可译作无分类域

间路由。这里的Classless是相对于分类法的Classful而言的。简

单地说,就是在一个IPv4地址的后面先加上斜线/,然后再加上

一个数字,用这个数字来指明在这个32位二进制IPv4地址中,使

用前面多少位来表示网络ID。如192.168.1.123/24,意思就是使

用前面的24位(前面三个字节,因为每个字节是8位,故3*8=24)

来作为网络ID,即“192.168.1”是网络ID,而剩下的8位(最后

一个字节)作为主机ID,即本例中的“123”。

2. 子网

处于同一个网络(子网)里面的所有设备都具有相同的网络ID,不同的仅仅是它们的主机ID。与集线器和二层交换机不同,路由器的每一个接口都有一个网卡,也就是说路由器的每一个接口都有一个IP地址。当一个子网和路由器的一个接口直接相连时,该接口的IP地址的网络ID也必须和该子网的网络ID一致。

3. 默认网关

在同一个网络(子网)里的所有设备,即具有相同网络ID的所有设备,都可以直接通信。比如主机A和主机B在同一个网络(子网)里,那么A可以把数据直接发送给B,B也可以直接把数据发送给A。如果A和B不在同一个网络里,即它们的网络ID不一样,那么A和B不能直接通信。如果A要向B发送数据,则必须先把数据发送给A的网关,再由A的网关来想办法把数据发送给B(注意,B和A的网关并不一定直接相连)。

默认网关是一个网络(子网)的默认出口点,所有发往其他网络的数据都会经由默认网关转发出去。由于路由器连接多个网络并且在网络间转发数据,所以一般都将路由器作为默认网关。

一个网络(子网)的所有主机都需要配置一个默认网关,以便其能够访问外网。在Windows命令控制台输入ipconfig /all命令可以看到网关的配置信息,如笔者机器上的输出信息如图2-9所示。图2-9 使用ipconfig /all命令查看网关配置信息

回过头来看图2-8所示的例子,可以看到一共有两个子网:左边的192.168.1.0/24(CIDR划分方法)和右边的192.168.2.0/24。两个子网通过中间的路由器相连接。左边子网里的两台主机的默认网关都是192.168.1.1,即路由器左边接口的IP地址;右边子网里的三台主机的默认网关都是192.168.2.1,即路由器右边接口的IP地址。

现在左边子网里的主机192.168.1.2要把数据包发送到右边子网里的主机192.168.2.8。下面来分析数据包发送的过程。

步骤 01 当主机192.168.1.2要向192.168.2.8发送数据包时,它会检查目标IP地址,发现其网络ID(192.168.2)和自己的网络ID(192.168.1)不同,所以知道不能直接发送,而只能把数据包发往默认网关(192.168.1.1),即中间的路由器。

步骤 02 路由器从接口192.168.1.1接收到数据包后,检查数据的目标IP地址,发现其网络ID是192.168.2,通过检查其路由表(将在后面的章节详细讨论),发现应该把数据包转发到接口192.168.2.1。

步骤 03 路由器的接口192.168.2.1接收到数据包后,检查数据的目标IP地址,发现其网络ID(192.168.2)和自己的网络ID(192.168.2)一致,所以它知道可以把数据包发送到目标地址,即直接发送到192.168.2.8。2.6 本章小结

本章首先介绍了数据传输的三种方式:单播、组播和广播;接着介绍了4种主要的网络设备:集线器、交换机、桥和路由器,这些设备都分别工作在OSI特定的层上。另外还介绍了广播域和冲突域的概念,以及它们与网络设备之间的关系。表2-1对这些知识点做了一个总结和比较。表2-1 4种常用网络设备特性的比较  第3章IP从本章节可以学习到:● IP概述● IPv4地址● IP路由● 分段和重组● IP包头3.1 IP概述

IP(Internet Protocol)是非常重要的网络协议,目前整个互联网都是基于IP的,所以理解IP对于网络编程也非常重要。我们在第1章讨论OSI第三层网络层和第2章讨论路由器的时候,都曾简单介绍过IP,本章将对IP展开详细的的讨论。由于现在IP有两个版本,即IPv4和IPv6,而IPv4是普遍存在的,所以本章主要讲述IPv4。

在第1章的时候提到,IP主要关心的是如何把数据从一个设备发送到另外一个设备。更加准确的说法应该是,IP的主要工作是把IP数据报从一个设备经由一个互联网络(Internetwork)发送到另外一个设备。注意,这里的互联网络主要是指一系列相互关联的网络,当然也可以指本地网络。为了达到这个目标,IP必须提供三个最基本的功能,即地址、路由、分段和重组。本章将分别介绍这三个功能。在学习了这三个基本功能之后,我们再来看IPv4头的几个关键字段,因为设计这些字段正是为了实现这三个基本功能。3.2 IPv4地址

网络中的任何一台设备都要通过网络接口卡(NIC)接入网络,如果该台设备想要被其他设备访问到,那么其网卡必须有一个唯一的地址。一台设备还可以有多个网卡并同时接入多个网络,相应地该设备就有多个地址,如果这个设备是主机的话,一般被称为multihomed主机。当然,路由器一般有多个网卡并接入多个网络,所以路由器也有多个地址,但是一般不把路由器称为multihomed主机。

IPv4使用一个32位二进制地址,所以理论上可供使用的IPv4地址一共有4 294 967 296个,即232。为了便于理解,这些32位整数的IPv4地址一般使用点分十进制(Dotted-Decimal)的形式来书写,即用点(.)隔开的4个十进制数,每个十进制数代表32位里面的一个字节,即8位。如192.168.1.123就对应于二进制的11000000 10101000 00000001 01111011,同样也对应于十进制的3 232 235 899。

为了便于管理和寻址(路由),一个IPv4地址的32位被划分为两部分:网络ID和主机ID。从左边开始的、连续的若干个二进制位作为网络ID,用于标识设备所在的网络;剩余的二进制位作为主机ID,用于标识在网络中的设备。那么该如何进行划分呢?或者说该用左边开始的多少位作为网络ID呢?由于历史的原因,目前一共有三种划分方法:分类法、子网化和CIDR。下面各小节将详细讨论这三种划分方法。3.2.1 分类法

1. 基本划分

在第2章曾说过,分类法(Classful Addresssing)是最早的、也是最简单的一种划分方法。它把IPv4地址固定地分为五类:A、B、C、D和E。A类把前8位划分为网络ID,B类把前16位划分为网络ID,C类把前24位划分为网络ID,D类用于组播,E类作为预留地址,所以D和E并不划分网络ID。其实这种说法比较笼统,实际的情况要更复杂一些。更加准确的说法应该是:A类把前8位划分为网络ID,但第1位必须为0;B类把前16位划分为网络ID,但前2位必须为10;C类把前24位划分为网络ID,但前3位必须为110;D类用于组播,但前4位必须为1110;E类作为预留地址,但前4位必须为1111,如图3-1所示。图3-1 分类法的五类地址

下面来分析一下图3-1。首先来看A类,由于A类前8位为网络ID,并且第一位必须为0,所以A类的网络ID的取值范围是00000000~01111111,即0~127;由于对剩下的24位主机ID没有任何限制,所以A类的主机ID的取值范围是0.0.0~255.255.255。将两者结合起来就是A类IP地址的取值范围,即0.0.0.0~127.255.255.255。同理,我们也可以推算出其他四类IP地址的取值范围,如表3-1所示。其中,A、B和C类的网络ID用下划线标出。表3-1 分类法的五类地址取值范围注意在表3-1中,从A到E的取值范围是连续的,即从A类的第一个地址0.0.0.0开始到E类的最后一个地址255.255.255.255,中间并没有任何间断。

分类法的特点就是能够很容易并且很快速地确定任意一个IPv4地址的分类,因为最多只需要检查其开头4位就能确定下来了。代码3-1就可以用来判断任意给定IPv4地址的分类。

代码3-1:char GetIPv4Class(unsigned int addr){ char addr_class = 'A'; for(;addr_class < 'E'; ++addr_class) { addr = addr << 1; __asm { JNC END_FOR } }END_FOR: return addr_class;}

其中,函数GetIPv4Class的参数是一个IPv4地址,如3232235899,即192.168.1.123,返回值是该IPv4地址的分类。在每次循环中,第6行把地址左移1位,被移出的最高位就变成了CPU的进位标志位(CF,Carry Flag)。由于C/C++语言不支持读取CPU的标志位,所以第7~10行使用了内嵌汇编语言,JNC END_FOR用来检测进位标志位,意思是没有进位(即CF == 0)就跳转到END_FOR,即结束循环。对照图3-1,可以看到,如果参数是一个A类地址,那么在第一次循环的时候(即addr_class == 'A'),由于A类地址的第一位是0,所以当对其左移1位的时候,进位标志位CF就被置为0,JNC的跳转条件成立,所以循环结束。可以看到,循环最多被执行4次就可以确定任意IPv4地址的分类了。

2. 特殊地址

一旦确定了一个IPv4地址的分类,根据图3-1,马上就可以确定该地址的网络ID和主机ID。理论上,除了D类和E类地址不能用作某一具体主机的IP地址外,还有A、B、C三类地址可供使用。但实际上,在A、B、C三类地址中也有很多预留的地址,以及某些地址范围有特殊的含义,下面列出一些常见的特殊地址。(1)网络地址

当一个IPv4地址中的主机ID的二进制位全为0时,该地址用来表示其网络ID所表示的网络,如192.168.1.0就表示网络ID为192.168.1的这个网络。(2)广播地址

当一个IPv4地址中的主机ID的二进制位全为1时,该地址用来表示其网络ID所表示的网络的广播地址,如192.168.1.255,这是一个C类地址,但由于其主机ID是255,即二进制的11111111,所以其用于表示192.168.1.0这个网络的广播地址。(3)当前网络的主机地址

当一个IPv4地址中的网络ID的二进制位全为0时,该地址用来表示在当前网络、其主机ID所表示的主机。如0.0.0.123这个地址,表示的就是当前网络的主机ID为123的主机。(4)通配地址0.0.0.0

通配地址用来表示本机的任意一个IP地址。当一个主机有多个网卡的时候,如multihomed主机,这个地址就很有用。在用socket编写服务器程序的时候,用来做监听的socket需要和本机的IP地址绑定起来,这个时候可以使用通配地址INADDR_ANY,表示希望接收来自所有可用网卡接口的客户连接请求。而在winsock2.h头文件里面,INADDR_ANY就定义为0x00000000,即0.0.0.0。(5)环回地址(loopback)

在A类地址中,从127.0.0.0~127.255.255.255的所有地址被称为环回地址。顾名思义,环回就是自己发给自己,即所有发送到该地址范围的数据都是发送给本机。结合在第1章讲到的OSI分层概念,发送到环回地址的数据从上向下到达第三层网络层,在离开网络层后又被直接作为输入传回给网络层,而不是传给第二层数据链路层。这样做的目的是为了测试,使得在同一台主机上的服务器和客户端程序能够相互通信。一般来说,我们都使用127.0.0.1作为环回地址,并且其名字一般为localhost。在winsock2.h头文件里面,INADDR_LOOPBACK被定义为0x7f000001,即127.0.0.1。

有时在测试的时候,我们需要使用一些网络抓包工具(如Wireshark等)来分析网络中的数据流,这时会发现这些工具抓不到发送到环回地址的数据,其实就是因为发送到环回地址的数据经过网络层之后就折返回去了,所以这些针对网卡的工具就看不到。但是也有一些技巧,可以让这些工具抓到发往127.0.0.1的数据。我们将在后文讲解路由表时,再来介绍如何操作。(6)私有地址

如果由用户来管理一个私有网络,那么用户可以给这个网络里面的主机分配任意IP地址。但是当用户把网络接入公网后,就必须保证所使用的IP地址不和公网里的IP地址发生冲突。有什么好的方法来保证呢?最直观的方法就是在用户的网络里全部使用全球唯一的IP地址,但正如你所见,对于现在的互联网来说,IPv4地址十分有限,所以这个方法不现实。既然使用全球唯一的IP地址不现实,也就是说不能保证你所使用的IP地址的唯一性,那如何避免冲突呢?办法就是使用特殊的IP地址,这些IP地址的特殊之处就在于其不被公网所认可,既然不被公网所认可,那么当然就不会和公网IP地址发生冲突了。这些特殊的IP地址被称为私有地址,RFC 1918给出了这些地址的范围。● 10.0.0.0~10.255.255.255(A类)。● 172.16.0.0~172.31.255.255(B类)。● 192.168.0.0~192.168.255.255(C类)。

除此之外,还有一个地址范围169.254.0.0~169.254.255.255,是在主机自动私有地址分配(Automatic Private IP Addressing,APIPA))时使用的。在没有DHCP服务器的网络环境下,各个主机可以使用APIPA来自动分配地址,使得它们之间仍然可以通信。

上面列出的这些私有地址在公网中都是无效的,所以也就不存在冲突的问题了。但是这也导致了另外一个问题,就是使用这些私有地址的主机如何才能和公网进行通信呢?我们将要在后面的章节所讲到的NAT(Network Address Translation,网络地址转换),就可以解决这个问题。(7)保留地址

下面列出的地址都是保留地址,不能用来分配给主机。● 0.0.0.0~0.255.255.255● 128.0.0.0~128.0.255.255● 191.255.0.0~191.255.255.255● 192.0.0.0~192.0.0.255● 223.255.255.0~223.255.255.255注意0.0.0.0这个地址虽然是通配地址,但其实它也是一个保留地址,尽管我们可以在程序里面使用它,但是不能把它作为IP地址来分配给一台主机。

3. 分类法的优缺点

分类法的优点是简单明了。由于地址本身就包含了类别信息,所以并不需要额外的信息(如我们下面将要谈到的子网掩码)来确定一个地址的网络ID和主机ID。同时,如代码3-1所示,网络设备(如路由器等)能够以极快地速度来确定一个地址的网络ID和主机ID,这对于处于网络干道上的、需要处理海量路由信息的路由器来说,无疑是一个不可忽视的优势。

分类法是最早提出来的IPv4地址划分方案,在当时的环境下,人们很难想象得到网络能够发展到今天这样的规模。所以以当时的眼光来看,把地址划分为A、B、C、D、E五类不失为一个好的方案,因为其简单,并且A、B、C正好对应三种规模的网络:A类对应于(超)大规模的组织机构网络,因为其主机ID一共有24位,即最多可容纳16 777 216台设备(更准确的说法应该是16 777 21622台,因为主机ID全为0或全为1时分别作为网络地址和广播地址,在本书中为了论述方便,都没有减去这两个地址);B类对应于中等规模的组织机构网络,其主机ID一共有16位,即最多可容纳65 536台设备;C类对应于小规模的组织机构网络,其主机ID一共有8位,即最多可容纳256台设备。但是在今天看来,这种方法明显缺乏灵活性和伸缩性,试想有哪一个组织机构网络会需要16 777 216台设备?如果一个组织机构网络需要1000台设备,那么给它分配一个C类网络是不够的,如果给它分配一个B类网络呢?倒是足够了,可是却浪费了64 536个地址。当然也有不浪费的办法,就是给它分配4个C类网络,但这样却给管理带来了不便,同时也增加了路由器的压力,因为原本只需要一条路由信息就可以访问到这1000台设备,现在却至少需要4条路由信息。也就是说,分类法灵活性不够,不能很好地适应千变万化的网络规模。

另外,由于一个组织机构里面往往有多个部门,为了更好地管理,每个部门往往都需要一个单独的子网络,但是分类法在给一个组织机构分配了一个网络地址后(一般是B类或者C类),该机构里的所有部门就只能属于同一个网络,也就是说分类法并没有考虑到一个机构里面可能存在多个子网络的问题。下面一小节要讨论的子网化(Subnetting)方法,就是为了解决这个问题。3.2.2 子网化

为了解决分类法不能很好地适应一个网络里可能存在多个子网络的问题,人们引入了子网化的概念。所谓子网化,就是在原有分类法的三类网络A、B和C的基础上,对其进行再划分,细分出能够适应各种网络规模的子网(Subnet)。具体地说,就是在A、B和C类地址的基础上,对其主机ID部分进行再划分,即使用主机ID的前若干位作为子网ID,剩余的位作为在该子网里的主机ID。也就是说,把原来分类法对IPv4地址所定义的二级结构:网络ID和主机ID,变成一个三级结构:网络ID、子网ID和主机ID。注意:网络ID是保持不变的。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载