一 单工/半双工/全双工通信的概念
1.单工通信:
单工通信定义:信息在两点之间只能单方向发送的工作方式.它的意思是指:假设A 和B 通信,只能由一方向另一方发送数据而不能接收来自另一方发送来的数据.就像小朋友们玩的听筒,在两个杯子之间系上一条线再拉紧,这就可以对着杯子说话而另一边能够听到声音.
图一 一个小孩对着罐子说话而另一个小孩在当听众
2.半双工通信:
半双工通信定义:信息在两点之间能够在两个方向上进行发送,但不能同时发送的工作方式.这就表示发送/接收数据 是有先后顺序的,比如:A 向B 发送数据请求后A 只能接收来自B 发送来的回传数据,但A 接收完来自B 发送来的会传数据后又可以立即向B 发送数据请求,而且B 也可以向A 发送数据.
图二 "对讲机"式问答
3.全双工通信:
全双工通信定义:通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合.全双工通信和半双工通信的本质区别是半双工通信双方只共用一条线路实现双向通信,但全双工通信却利用两条线路,一条作发送数据用,另一条作接收数据用.
图三 有线固定电话的模型
二 芯片间通信
1.串口通信:
主机和主机之间的通信,实质上就是两颗芯片之间来回传输数据..
图四 串行接口实物图
串口通信是通过全双工通信进行的按位传输的通信.它的优点是可以长距离传输数据(通过太长的数据链路时信号是会减小的,但一般我们利用信号放大来实现更远的数据传输),占用线路少(发送线路,接收线路,地线[主要是为了抗干扰]).不过串口通信比并口通信稍微慢些.一般我们使用RS-232 号传输标准来规范数据传输.
图五 串口针脚顺序图
对于DB 9脚的串口接口定义:2号线路 接收数据(RxD),3号线路发送数据(TxD),5号线路信号地(GND)[其用意就是屏蔽掉外界的电磁干扰]
*RS-232 协议设计:
图六89S51 系列单片机与PC 间的通信
对于某些没有输出RS-232信号的芯片,设计者常用MAX 232 (芯片通信输出的TTL 电平转换到RS-232信号的器件) 来把PC 和该芯片相联.在图六中,89S51 首先通过TxD 发送数据到MAX 232 T1IN,然后MAX 232 在它的内部把TTL 电平信号转换为RS-232信号,最后MAX 232 通过T1OUT 发送到PC 的COM 接口,此时PC 就接收到了我们发送来的数据(反过来就是接收数据:COM TxD ->R1IN ->R1OUT).
三 通信协议
1.以太网 传输协议:
以太网定义:当前广泛使用,采用共享总线型传输媒体方式的局域网.过去的年代,多台计算机要想利用一个Moden 上网的话,就需要添加一块集线器(HUB ) 来把这些计算机并联起来.[PS:集线器和交换机(SWITCH) 相比,集线器会把总网络数据传输速率平均分配到每台计算机,但交换机却不会,这和硬件设计有关]
图七 集线器实物图(这年头找张没有水印的图片还真少啊..)
下面就是多台计算机共享网络线路的拓扑图.
图八 总线型数据传输链路
线路倒是共享了,作为在线路中的某台计算机是怎么知道线路中的数据到底是发送到自己还是发送到其它计算机的呢?为此人们制定了以太网数据传输协议,下图是传输数据结构.
图九 以太网数据传输结构
目的地址 指的是该数据是由哪台计算机接收.源地址 就是这个数据是从哪儿发送的.打个比方:比如A 主机需要发送数据到广域网,那这个目的地址就填写集线器的网络适配器的地址(这个地址就做MAC地址,它是网络适配器所拥有的唯一地址). 当集线器接收到数据并转发B 主机时,总线上所有主机都可以接收都这个数据包,假设A 主机接收到这个数据包,它会把数据包中的目的地址和自己的网络适配器作对比,相同的话则表明这个数据是传递到我的,若不相同则丢弃数据包.这也就解释了同集线器总线下监听其它主机发送/接收网络信息的原理.
以太网数据包有许多不同的类型,上面是在集线器下常用的三个类型:IP 数据传输[0x0800],ARP 请求/应答[0x0806],RARP 请求/应答[0x8035].
ARP 请求/应答:它的用处是利用某个网络适配器的地址在总线中发起询问,然后得到要查询的网络适配器的IP 地址.由于在计算机需要依靠集线器或交换机或路由器来传递消息之前,它一定要利用ARP 请求告诉集线器等转递消息硬件本机的网络适配器的MAC 地址[PS:也可以利用RIP (路由信息协议)协议来向转递消息硬件获取IP地址(发送网络适配器的MAC地址获取IP 地址)].在转递消息硬件接收到这个请求后会在ARP 缓存表(对应着计算机的IP地址和网络适配器的MAC 地址)中查找,若无该MAC 地址,则在ARP 缓存表更新该MAC 地址,然后发送ARP 应答数据包,那么当转递消息硬件接收到消息后就可以根据数据中的IP 地址在ARP 缓存表寻找MAC 地址然后就在总线上发送.假如接收到一个数据包的的IP 地址在ARP 缓存表中找不到的话,那转递消息硬件将会丢弃该数据包并向源IP 地址发送ICMP 数据不可到达的数据包.注意,转递消息硬件一般是三十分钟刷新一次ARP 缓存表的.
RARP 请求/应答:假如我们只知道同集线器下的某台计算机的IP 地址并想发送数据给它但又没有该计算机的网络适配器的MAC 地址那怎么办呢?那就需要向总线广播RARP (反向地址转换协议)请求,此时以太网数据结构中的目的地址置为FFFFFFFFFFFF (即:-1),RARP 数据包结构(见图十三)中的目的IP 地址则置为需要查询的IP 地址.接下来,当总线下的某台计算机的网络适配器接收到后就会把该IP 和自己的对比,假若查询的是自己的IP 地址,那就返回包含这个网络适配器的IP 地址和MAC 地址的RARP 应答,最后查询主机接收到该数据包后就更新本机的ARP 缓存表,然后就可以进行IP 层的数据发送了.
图十 ARP /RARP 数据包结构
2.IP 协议:
由于以太网协议只适用于局域网,而且以太网数据不能跨转递消息硬件发送,所以人们制定了IP (Internet Protocol ,因特网协议)协议.有了它,只要计算机连接到因特网那它都可以利用IP 地址(就像手机号码) 来实现通信(就像手机利用GSM 协议打电话).下面就是IP 协议数据包结构:
图十一 IP 协议头部数据包结构
源IP 地址和目的IP 地址的意思和以太网数据包结构中的源地址和目的地址作用相同.(这里略去了其它TCP 特性,因为它们与本文无关)
读者们先来看看下面的网络拓扑图:
图十二 网络门禁系统的网络拓扑图
在每一个门禁控制系统里面都有主控制器.而这些主控制器利用以太网通过交换机来实现把数据传递到因特网(Internet)上.由于以太网传输协议只能使用在同一以太网下,所以这些数据是不可能传递到这个区域的外面的.你可以这样想一下:广州分厂的其中一个门禁控制系统的主控制器向它所属的以太网发送一条信息给上海分厂的管理电脑及卡证中心主机显然是不行的.而IP 协议却不同,IP (Internet Protocol) 协议适合所有只要连接到因特网而且还拥有其独立的IP 地址的主机.所以,当广州分厂的其中一个门禁控制系统要和上海分厂的管理电脑及卡证中心主机实现数据交换那就必须要知道该主机的IP 地址.有了它,系统会根据实际情况把IP 协议头部数据包的各个数据填充好,然后通过以太网指定发送到交换机.交换机会再把我们的数据包转发到因特网上,接下来这个数据包会到达上海分厂的交换机, 最后上海分厂的交换机通过以太网发送数据包到管理电脑及卡证中心主机.
以IP 协议为基础,我们还可以利用TCP 和UDP 的传输数据方式来实现数据的传输.一般地,TCP 会提供"无差别","可靠的" 的数据传输服务.
3.TCP 协议:
TCP 协议作为现在广泛使用的协议,它有着许多网络通信协议所没有的特性(比如:重传).TCP 协议是基于IP 协议上开发的.下面先来讨论TCP 的数据包结构:
图十三 TCP协议头部数据结构
TCP 协议并没有指定发送方/接收方的地址,因为它是以IP 协议作为基础的协议,所以IP 协议的地址也可以说是TCP 协议的地址.在TCP 协议头部数据结构里,有一个新名词叫"端口",它的用意是为了标识不同的程序接收不同的数据包,比如:80 端口发送/接收HTTP 协议数据包,21 端口实现TELNET 协议 等.TCP 协议的传输机制是比较特殊的,它首先需要两台主机之间建立通信连接,然后才可以传输数据,最后数据传输完成的时候还必须要对这个连接进行关闭.先看看下面是TCP 的通信流程图:
图十三 TCP 协议通信连接与关闭连接时数据包传送情况(由于源图被画了很多红圈,没办法啊只能抢救成这样,原谅LC 吧)
对于上面的数据包交换我们可以分为两部分来分析:前三个数据包表示的意思是建立TCP 连接,后四个数据包的意思是关闭TCP 连接.
在TCP 建立连接的时候,主动建立的一方将会发送SYN_SENT 类型的TCP 数据包到目的主机,目的主机处理完成这个连接请求后立即返回SYN_ACK类型的TCP 数据包(编者注:无论目的主机是否愿意和它建立连接,要想实现这个结构那就必须忽略防火墙等的外界影响条件),最后在主动建立的一方接收到该SYN_ACK 数据包后返回ACK 数据包,它也就代表了TCP 连接真正建立成功.这就是TCP 三次握手过程.
两台主机之间的数据传输结束了,那就要关闭连接.当一方主动关闭连接时,它将会发送FIN 数据包来通告对方.对方接收FIN 数据包后就会返回FIN_ACK 数据包来确认.(编者注:凡是已经主动发送过FIN 数据包的主机都不能够再发送任何数据,但可以接收数据)只有双方都各自都完成了发送FIN 数据包,那么TCP连接也就关闭了.这就是TCP 的四次握手过程.
发送数据和这些差不多,有兴趣的读者可以看看<<TCP/IP 协议详解>> 或者给LCatro 留个言.
4.小总结:
数据包的结构搞乱了?请看看下图吧..
图十四 网络数据包结构
由于我们在以太网下利用以太网协议发送数据,所以我们的要发送到目的主机的数据就包含在以太网数据包的数据里面.对于这个数据,实际上是IP 数据包,然而IP 数据包里面的数据其实是TCP 数据包,TCP 数据包里面的数据就是我们要发送的信息.所以读者们结合上图来理解网络数据包结构(右边)就容易了..
至于左边的结构图的意思是网络模型,它代表了哪个协议所在哪一个网络模型层的级别.
四 网络适配器(网卡)原理:
1.什么是网络适配器:
网络适配器的意义在于协助计算机处理器来实现数据的传输.
下面是实物图片,这个网络适配器是台式计算机使用的.
图十五 网络适配器实物图
由于现代计算机发展迅速,导致网络服务器数据传输速度有些时候并不能满足日益增长的需求.为此,双端口网络适配器诞生了,也即是说同一个网络适配器可以连接两条网线.(HP CN1000E双端口聚合网络适配器 - 产品简介)
图十六双端口聚合网络适配器
*网络适配器的普通模式和混杂模式:
一般情况下,我们都使用网络适配器的普通模式.所谓普通模式,其实是让网络适配器只接收发送到自己的数据包.但混杂模式却与此相反,凡是网络适配器接收到数据包就传递给处理器,无论这个数据包是不是发送该主机的.
*关于网络适配器的混杂模式
由于数据的传输都是按照一定的标准的,那么只要有多台主机在同一以太网下,其中一台主机就可以利用混杂模式来获取其它计算机发送/接收的数据包.(请回顾下:"图八 总线型数据传输链路",在总线下传输的数据各个主机都可以接收到)所以这就是局域网下监听其它计算机的原理.同样地,我们也可以利用此原理去盗取用户帐号和密码等敏感信息.但在盗取成功之前还需要一个前提:数据的解密.
五 Windows 驱动层:
1.WinSock 函数库:
WinSock 是Windows 自带的与网络交互的运行库.在此,程序员们利用一些相关的接口就可以实现端口绑定,TCP 连接,关闭,发送,接收数据等功能.请注意,WinSock 只是网络接口,更准确地来讲就是DLL 文件(Dynamic Link Library ,动态链接库.它是用来储存代码或者资源数据的文件。所以WinSock 也只是通过调用驱动程序(驱动程序的用意是让处理器控制外围硬件)的方式来编写接口.接下来,你将会看到从网络适配器接收的数据需要经过多少个驱动才可以到达WinSock.DLL .
2.网络适配器递交数据需要经过的驱动:
在看内核网络驱动程序结构之前,我们首先要知道:
1.WinSock.DLL 其实是在TDI(Transport Driver Interface ,传输驱动程序接口.它的用意是把从上往下/从下往上 传递的驱动程序I/O 请求数据结构逐级搬运.在数据搬运的过程中,中间驱动程序可以对这些数据进行过滤)层上的.
2.Protocol Driver ,协议驱动程序.每个协议驱动程序都代表着不同的网络协议(编者注:Winpcap 和NDISUIO不是网络协议驱动程序.前者是Windows网络底层抓包驱动程序.后者是控制NDIS 驱动程序I/O 的驱动程序)
3.HAL 是硬件抽象层,当驱动程序的I/O 请求数据结构传输到此时,接下来就是处理器通过总线来控制外围硬件.
图十七 Windows 系统内核网络驱动程序结构
在普通程序调用WinSock.DLL 发送TCP 连接请求时,WinSock.DLL 会自动填写好该请求数据包的IP 及TCP 数据包头部结构.然后向下层驱动程序传递,直到TCP/IP 驱动程序.TCP/IP 驱动程序再转发到NDIS(Network Driver Interface Specification ,网络适配器驱动程序),最后通过HAL 实现把TCP 连接请求数据包从处理器发送到网络适配器.接下来网络适配器会通过网线发送到以太网.接收数据与此相反,略之.
六 在一次浏览www.baidu.com 中系统工作的过程
至此,相信读者们已经对于硬件间数据传输,网络协议,Windows系统内核网络驱动程序结构 都有了一定的了解.那LCatro 就和大家分析下浏览百度首页的过程吧.
假设我们刚刚把电脑启动完成,然后立即浏览百度首页.(这样做的用意是提供一个DNS 缓存表为空的环境)
图十八 使用程序浏览百度首页
在我们输入www.baidu.com (编者注:www.baidu.com 准备地来说是网站的域名) 使浏览器访问的时候,它会先把域名转换到IP 地址(即:解析,用gethostbyname() 函数实现) .此时WinSock 会从本地的DNS (用于解析域名和IP 地址的协议)缓存表(在本机里面的一张专门存放域名和对应的IP 地址的数据块)中寻找www.baidu.com 的IP 地址.由于主机是刚刚启动的,所以DNS 缓存表还是一片空白.WinSock 从DNS 缓存表中找不到对应的IP 地址,于是就向DNS 服务器发送查询域名请求(即:DNS 指针查询).DNS 服务器接收到该请求后会在本地查询该域名,假如该DNS 服务器没有该域名和对应的IP 地址的话,那该DNS 服务器便会向比它更高级的DNS 服务器提交查询,一直到查询结果得到为止.成功则返回查询成功数据包,如果还是查询不到的话DNS 服务器会返回查询失败数据包. [该过程为域名转换到IP 过程,用专业的语言来说就是:域名解析过程]
有了IP 地址,浏览器就向它发送TCP 连接请求,接下来就是三次握手过程.连接成功建立后,浏览器会向百度的服务器发送获取http://www.baidu.com/index.html (编者注:www.baidu.com/index.html 的意思是百度首页的index 索引网页的.HTML 文件(网页代码文件))的源代码.随后,百度服务器返回索引网页的源代码,并且主动关闭TCP 连接.最后浏览器便根据这里面的源代码逐一显示在程序的网页浏览控件上.
思考题:请你联系该文章所讲述到的知识认真地想一想系统是怎么样去一步步实现的呢?
与主题无关的相关知识:
*程序启动过程:
在我们双击程序时,Explorer.exe 会调用CreateProcess()运行该程序.CreateProcess() 立即读取程序文件(即:.EXE 文件) 的PE (PreInstallationEnvironment,预安装环境.这个是Windows 特有的程序结构,它的用意是告诉Windows 系统在运行程序之前需要先做哪些东西.Windows 系统会根据.EXE 的需求先做一些相关的工作,比如:程序需要加载到哪一个内存位置?程序代码的入口点在哪儿?系统加载完成后,就将这个程序从硬盘中把程序文件映射到内存中 (内存映射).接下来CreateProcess() 会给该程序分配堆栈,最后再创建线程来执行该程序.假如我们运行的是.INK 文件(即:快捷方式),Explorer.exe 会解析.INK 文件,从中获取到目的程序的运行路径.
*VB 程序运行细节:
由于VB 程序在设计窗口界面的时候完全使开发者避免怎么样用代码把控件一个个创建.读者们可以联系下Win32 窗口程序的开发.首先,在WinMain() (即:Win32 应用程序入口点) 的时候程序就开始注册->创建窗口了.在创建窗口完成后(注意,此时窗口只是空白的!),Windows 系统会向该窗口发送WM_PRINT 消息通告窗口开始画控件.
Q:既然说刚刚创建窗口的时候是空白的,那为什么我们没有先看到空白的窗口再看到程序一步步在窗口上面画控件呢?
A:因为处理器执行代码的速度太快了,所以它在绘画的过程中只使用了非常短的时间,以至于人类的眼晴不能接收到这些图像.
*内核处理按键过程:
在我们输入完成网址后按下键盘的Enter 键,键盘会主动向处理器引发中断事件.由于计算机系统中中断种类太多,而且对于不同的中断有不同的处理方法,于是人们把各个不同的中断处理程序的入口地址储存在中断程序入口表.这是键盘所引发的中断,那处理器接收到这个中断的时候立即跳出当前正在运行的程序,转而去运行键盘中断程序,当键盘中断程序执行结束后,处理会继续执行原先的暂停运行的代码.
这个被按下的按键在处理器里面是用ASCII 码来保存的,并且它也会从最底层驱动一直上传到应用程序.应用程序是通过系统发来的WM_KEYDOWN 消息然后来获取按下的键值的.