Archive for 2006年7月24日


Debian有关网络的一些基本信息

1. 网络相关配置文件介绍

1.1 /etc/hosts

包含(本地网络中)已知主机的一个列表。如果系统的 IP 不是动态获取,就可以使用它。对于简单的主机名解析(点分表示法),在请求 DNS 或 NIS 网络名称服务器之前,/etc/hosts.conf 通常会告诉解析程序先查看这里。

文件格式:
ip地址          主机名          别名

$ cat /etc/hosts

127.0.0.1       localhost.localdomain   localhost 

1.2 /etc/services

Internet网络服务文件,将网络服务名转换为端口号/协议。由 inetd、telnet、tcpdump 和一些其它程序读取。文件中的每一行对应一种服务,它由4个字段组成,中间用TAB或空格分隔,分别表示“服务名称”、“使用端口”、“协议名称”以及“别名”。

文件格式:
服务            端口/端口类型           别名

$ cat /etc/services  |more

tcpmux          1/tcp                   # TCP port service multiplexer
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
discard         9/udp           sink null
systat          11/tcp          users
daytime         13/tcp
daytime         13/udp
netstat         15/tcp
qotd            17/tcp          quote
msp             18/tcp                  # message send protocol

1.3 /etc/hostname

主机名配置文件,该文件只有一行,记录着本机的主机名。

文件格式:

主机名
$ cat /etc/hostname 
tonybox

1.4 /etc/host.conf

当系统中同时存在DNS域名解析和/etc/hosts主机表机制时,由该/etc/host.conf确定主机名解释顺序。示例:

order hosts,bind    #名称解释顺序
multi on            #允许主机拥有多个IP地址
nospoof on          #禁止IP地址欺骗

order是关键字,定义先用本机hosts主机表进行名称解释,如果不能解释,再搜索bind名称服务器(DNS)。

1.5 /etc/nsswitch.conf

名称服务交换设定档。它控制了数据库搜寻的工作,包括承认的 主机,使用者,群组等。此外,这个档案还定义了所要搜寻的 数据库,例如此行:

hosts: files dns

指明主机数据库来自两个地方,files ( /etc/hosts file) 和 DNS, 并且本机上档案优先于 DNS。

$ cat /etc/nsswitch.conf 

passwd:         compat
group:          compat
shadow:         compat

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

1.6 /etc/resolv.conf

该文件是DNS域名解析的配置文件,它的格式很简单,每行以一个关键字开头,后接配置参数。resolv.conf的关键字主要有四个,分别是:

nameserver   #定义DNS服务器的IP地址
domain       #定义本地域名
search       #定义域名的搜索列表
sortlist     #对返回的域名进行排序

下边是一个示例:

#cat /etc/resolv.conf
domain mydebian.com
nameserver 192.168.1.1  //最多三个域名服务器地址

1.7 /etc/network/interfaces

网络接口参数配置文件, 下面是一个配置示例, 有两个网络接口, 其中eth0 分配静态IP地址, eth1动态获取IP地址 :

       # This file describes the network interfaces available on your system
      # and how to activate them. For more information, see interfaces(5).

      # The loopback network interface
        auto lo
        iface lo inet loopback

      # The primary network interface
        auto eth0
        iface eth0 inet static
                address 192.168.1.254
                network 192.168.1.0
                netmask 255.255.255.0
                broadcast 192.168.1.255
                gateway 192.168.1.1

        auto eth1
        iface eth1 inet dhcp

如果对此文件进行修改, 需要重启网络方能生效:

        # /etc/init.d/networking restart

2. 基本的网络配置命令和脚本

2.1 etherconf

Debian 下提供一个名叫 etherconf软件包, 用于配置网络信息,这包括主机名,IP,DHCP,DNS,GATEWAY,NETMASK…等, 默认没有安装这一软件包, 需要您手动安装:

        # aptitude install etherconf

安装完毕后运行:

        $dpkg-reconfigure etherconf

进行配置.

这个软件会修改以下配置文件:

        /etc/resolv.conf
        /etc/network/interfaces
        /etc/hosts
        /etc/hostname

重复使用这一配置文件的方法是:

        # dpkg-reconfigure etherconf

2.2 /etc/init.d/networking

系统启动时的初始化脚本, 当系统以某个级别启动时, 它负责初始化所有的已配置的网络接口.

2.3 ifconfig

用于配置常驻内核的网络接口。它用于在引导成功时设定网络接口。此后,只在需要调试及系统调整时才使用。

命令格式:
        ifconfig [接口]
        ifconfig 接口 [aftype] options | address ...

如没有给出参数, ifconfig 显示当前有效接口的状态。如给定单个 接口 作为参数,它只显示给出的那个接口的状态;如果给出一个 -a 参数,它会显示所有接口的状态,包括那些停用的接口。否则就对一个接口进行配置。

选项
        接口 接口名称。通常是一个后跟单元号的驱动设备名,例如第一个以太接口 eth0 。

        up
            此选项激活接口。如果给接口声明了地址,等于隐含声明了这个选项。 
        down
            此选项使接口驱动设备关闭。
        netmask addr
            为接口设定 IP 网络掩码。 
        add addr/prefixlen
            为接口加入一个 IPv6 地址。 
        del addr/prefixlen
            为接口删除一个 IPv6 地址。
        hw class address   如接口驱动程序支持,则设定接口的硬件地址。
此选项必须后跟硬件的类型名称和硬件地址等价的可打印 ASCII 字符。

  利用ifconfig命令查看网络信息:

ifconfig
   eth0    Link encap:Ethernet  HWaddr 00:15:58:3E:F2:6B  
           inet addr:192.168.1.254  Bcast:192.168.1.255  Mask:255.255.255.0
           inet6 addr: fe80::215:58ff:fe3e:f26b/64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:29458 errors:0 dropped:0 overruns:0 frame:0
           TX packets:23690 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1000 
           RX bytes:10945195 (10.4 MiB)  TX bytes:2935004 (2.7 MiB)
           Interrupt:169 Base address:0xe200 

   eth0:0  Link encap:Ethernet  HWaddr 00:15:58:3E:F2:6B  
           inet addr:192.168.1.244  Bcast:192.168.1.255  Mask:255.255.255.0
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           Interrupt:169 Base address:0xe200 

    lo      Link encap:Local Loopback  
            inet addr:127.0.0.1  Mask:255.0.0.0
            inet6 addr: ::1/128 Scope:Host
            UP LOOPBACK RUNNING  MTU:16436  Metric:1
            RX packets:354 errors:0 dropped:0 overruns:0 frame:0
            TX packets:354 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:0 
            RX bytes:45062 (44.0 KiB)  TX bytes:45062 (44.0 KiB)

    ppp0    Link encap:Point-to-Point Protocol  
            inet addr:18.18.18.13  P-t-P:18.18.18.1  Mask:255.255.255.255
            UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1396  Metric:1
            RX packets:9631 errors:0 dropped:0 overruns:0 frame:0
            TX packets:9189 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:3 
            RX bytes:8460352 (8.0 MiB)  TX bytes:913898 (892.4 KiB)

ifconfig的第一种格式(或使用不带任何参数的ifconfig命令)可以用来查看当前系统的网络配置情况。

    * eth0 : 表示网卡代号
    * lo :Linux内部的网络回环地址, 用于模拟网络行为,
   * HWaddr :网卡的硬件地址,也就是MAC地址
    * inet addr :网卡的ip地址
    * Bcast :广播地址( broadcast ) ;
    * Mask :子网掩码;
    * MTU :最大传输单元的缩写(Maximum Trasmission Unit), 
标示此网络接口的可传输的最大封包, 此值的设定错误可能引起网络故障. * RX :网络从起动到现在为止数据的接收情况 * TX :网络从起动到现在为止数据的发送情况 * collisions :网络信号发生冲突的情况;

激活网络设备

        ifconfig eth0 up

更改网络设备信息

        #ifconfig eth0 192.168.1.112 netmask 255.255.255.0

关闭网络设备

        ifconfig eth0 down

修改网卡的MAC地址

        ifconfig eth0 down
        ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
        ifconfig eth0 up

3. 测试网络

3.1 ping

向网络主机发送ICMP回显请求(ECHO_REQUEST)分组 程序使用 ICMP 协议的强制回显请求数据报以使主机或网关发送一份 ICMP 的回显应答。回显请求数据报(“ pings IP 及 ICMP 的报头,后跟一个“时间值关键字”然后是一段任意长度的填充字节用于把保持分组长度为16的整数倍。以下是程序的选项:

ping [-c count] [-i wait] [-p pattern] [-s packetsize] [-t ttl] destination

   -c
        count 在发送(和接收)了正好数量为 count 的回显应答分组后停止操作。
   -i(此选项与-f选项不能同时使用。)
        wait 在发送每个分组时等待 wait 个秒数。缺省值为每个分组等待一秒。

   -p(在网络上诊断与数据相关问题时此选项很有用。)
        pattern 可以指定最多16个填充字节用于保持分组长度为16的整数倍。
例``-p ff''将使发出的分组都用全1填充数据区 -s packetsize 指定要发送数据的字节量。 缺省值为56,这正好在添加了 8 字节的 ICMP 首部后组装成64字节的 ICMP 数据报。 -t ttl指存活数值TTL的大小默认为255

        tony@tonybox:~$ ping www.linuxsir.org -c 4
        PING www.linuxsir.org (218.61.34.138) 56(84) bytes of data.
        64 bytes from 218.61.34.138: icmp_seq=1 ttl=52 time=103 ms
        64 bytes from 218.61.34.138: icmp_seq=2 ttl=52 time=125 ms
        64 bytes from 218.61.34.138: icmp_seq=3 ttl=52 time=126 ms
        64 bytes from 218.61.34.138: icmp_seq=4 ttl=52 time=110 ms

        --- www.linuxsir.org ping statistics ---
        4 packets transmitted, 4 received, 0% packet loss, time 3003ms
        rtt min/avg/max/mdev = 103.513/116.329/126.598/9.856 ms
        tony@tonybox:~$ 

3.2 route

Route route 程序对内核的 IP 路由表进行操作。它主要用于给那些已经用 ifconfig(8) 程序配置过的接口指定主机或网络设置静态路由。

当使用了 add 或 del 选项的时候, route 修改路由表.如果没有这些选项, route 显示当前路由表的内容.

        # route [-nee]
       # route add [-net|-host] 目标主机或网络 [netmask] [gw|dev]
       # route del [-net|-host] 目标主机或网络 [netmask] [gw|dev]

    -n   :数字地址形式代替解释主机名形式来显示地址。
此项对检测为何你到域名服务器的路由发生故障的原因非常有用。 -ee   :将产生包括选路表所有参数在内的大量信息 add   :添加一条路由 del   :删除一条路由 -net  :路由目标 target 为网络。 -host  :路由目标 target 为主机。 netmask :为添加的路由指定网络掩码! gw    :通过一个网关进行包路由.

注意:

指定的网关首先必须是可达的。也就是说必须为该网关预先指定一条静态路由。如果你为本地接口之一指定这个网关地址的话,那么此网关地址将用于决定此接口上的分组将如何进行路由。这是兼容 BSD 风格。 dev   :强制路由与指定的设备关联,否则内核自己会试图检测相应的设备 (方法是检查要增加的路由项所处环境中已存在的路由和设备声明)。在多数正常的网络上无需使用。

    # route  查看本地路由信息
    tonybox:/etc/network/run# route
    Kernel IP routing table
    Destination   Gateway  Genmask         Flags Metric Ref    Use Iface
    18.18.18.1    *        255.255.255.255 UH    0      0        0 ppp0
    192.168.1.0   *        255.255.255.0   U     0      0        0 eth0
     default      *        0.0.0.0         U     0      0        0 ppp0

        route add -net 127.0.0.0
            加一条普通的回环记录,它使用掩码 255.0.0.0 
(从目标地址可以判断它是 A 类网)并与设备 "lo" 相关联 . route add -net 192.168.1.0 netmask 255.255.255.0 dev eth0 给通过 "eth0" 的路由表添加一条指向网络 192.56.76.x 的路由。
其中C类子网掩码修饰词并不是必须的,因为 192.* 是个C类的IP地址。这里可省略关键字"dev" route add default gw 192.168.1.1 加入一条缺省路由(如果无法匹配其它路由则用它)。
使用此路由的所有包都将通过网关 192.168.1.1进行传输。 route add 224.0.0.0 netmask 240.0.0.0 dev eth0 此命令设定所有 D 类地址(用于组播)的路由通过 "eth0" 进行。
这是用于带组播的内核正确的配置行。

3.3 traceroute

        traceroute [ -dFIlnrvx ] [ -f first_ttl ] [ -g gateway ]
                       [ -i iface ] [ -m max_ttl ] [ -p port ]
                       [ -q nqueries ] [ -s src_addr ] [ -t tos ]
                       [ -w waittime ] [ -z pausemsecs ]
                       host [ packetlen ]

通过Traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径。当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不一样,但基本上来说大部分时候所走的路由是相同的。UNIX系统中,我们称之为 Traceroute,MS Windows中为Tracert。 Traceroute通过发送小的数据包到目的设备直到其返回,来测量其需要多长时间。一条路径上的每个设备Traceroute要测3次。输出结果中包括每次测试的时间(ms)和设备的名称(如有的话)及其IP地址。

        -d
        指定不对计算机名解析地址。
        -h maximum_hops
        指定查找目标的跳转的最大数目。
        -jcomputer-list
        指定在 computer-list 中松散源路由。
        -w timeout
        等待由 timeout 对每个应答指定的毫秒数。
        host
        目标计算机的名称。

   # traceroute linuxsir.org
   traceroute to linuxsir.org (218.61.34.138), 30 hops max, 40 byte packets

4. 配置ADSL上网

首先,你要拥有上网帐号和密码, 并且有一块网卡正确的与ADSL moden正确相连

4.1 安装PPPoE软件包

        $ sudo install pppoe pppoeconf

4.2 然后进行配置

        确认检测到了您的网卡
        输入您的ADSL帐号
        输入您的ADSL帐号密码
        常规选项:是否修改默认路由: yes
                是否获取DNS: yes
        是否在引导时自动连接: yes
        是否马上建立连接: yes

完成这些步骤以后, 连接应该可以正常使用了

4.3 手动控制

        $ sudo pon dsl-provider #手动连接 
        $ sudo poff dsl-provider #手动断开连接

4.4 FAQ

Q:拨号成功, 但无法和外网通讯

A:使用route命令检查本地路由, 看默认路由是否正确

Q:无法解析域名

A:检查/etc/resolv.conf文件,看是否正确获取了DNS

Andrew Clarke 在 How To Be A Good Guru 一文中提到了 How to Answer Questions the Smart Way 这个有趣的话题, 并且模仿 提问的智慧 给出了"回答的智慧"的 10 条准则。来看一下这 10 条(翻译了一下,并适当的作了一点注释):

1. Don’t answer questions to which you don’t know the answer( 不回答自己不知道答案的问题)

2. Explain yourself (解释给自己)
如果自己是提问者,你的回答是否能让自己明白?

3. Give as little assistance as necessary (尽可能的给最少的帮助)
有的时候启发性的回答更为有效.

4. Show your workings (展示你的做法)

5. Use humour judiciously (明智地使用幽默)
有的时候因为不同语境/语言的问题,你的俏皮话可能会让提问者更加困惑。

6. If you can’t say something nice don’t say anything at all(如果你不能说出有用的内容,就别说)

7. Avoid jargon, baffling acronyms and idiolects (避免行话、令人困惑的缩写词、习惯用语)

8. Never never never just respond with RTFM. Not ever.(永远永远永远不要回复 RTFM)
这里的 RTFM 代表"Read The Fucking Manual", "去读该死的手册". 另外一个常见的是: STFW –Search The Fucking Web, "搜索该死的网络",或者友好一点的 "Google 一下". 对于中文论坛上,我觉得还有一个尽量不要说 "RPWT" –人品问题

9. Meditate on eternity (永远的深思熟虑)
回答的问题,可能在不久以后会被别人搜索到,看到,甚至是被你将来的老板看到。一个欠缺思索的回答无疑会降低你在其他技术人员心目中的形象。

10. Keep your newbie mind (保持自己的"新手"思维)
学无止境

保持谦卑。回答并不意味着你是"给予", 可能你也在学习. 不要认为回答了一些问题自己就成了 Guru 了.

上述 10 条应该建立在《提问的智慧》的基础上。

Andrew Clarke 的这篇文章是针对 DBA 来说的,不过对其他领域的技术人员也有借鉴意义。提问、回答都是一门艺术.

  序:去年为了总结自己所学习/接触过的技术,也顺便为初学者少走弯路指明一些方向,可惜后来诸事缠身未能继续,十分遗憾,现放到自己的BLOG上来鼓励自己将此继续下去。

  "Win32编程”
  很不幸,我从开始学习编程到理解这个名词中间隔了很长的时间(上个世纪的学习环境可见一斑)。很长时间里我都不明白32是指什么,我用过Dos,Win31,win95,win97…但好像没用过名为Win32的操作系统啊?很久以后我才知道,32在这里并不是指操作系统的版本号,而是指32位。微软操作系统在win31及其以前都是DOS系统,windows只是在dos下运行的一个大程序而已。在其后win95则稍有改变,windows除了DOS核心以外也真正成为了操作系统的一部分,提供着各类操作系统提供的服务。应该说,在win95之后的windows(新近的64位win系统以前)都可以称之为win32系统平台(95/98实际上是16与32位混合)。所以在这样的平台上,直接或间接使用系统提供的API编程,就称之为Win32编程。对Visual Studio而言,Win32编程一般指SDK、MFC、ATL这几类开发方法,其中ATL在国内应用不是很广泛,一般应用于以COM组件为架构的中大型软件产品。

  "SDK" :Software Development Kit,常译为软件开发(工具)包
  在Win32编程领域一般指与MFC这类框架编程相区别的,直接调用Windows提供的API的开发方式,与字面原意有一些区别。另外一个经常见到的说法就是某软件(硬件)带有自己的一套SDK,这里其实一般是指一套API库函数或者类库,供上一层的开发者调用。又譬如常说的DX的SDK,其实是微软开发的一套COM组件,供上层开发者使用。总之,供程序员使用的比较完备的代码库,就可以称之为SDK;

  “MFC”: Microsoft Fundation classes 微软基础类库
  大家都知道,使用SDK编程方式往往有很多每次都重复的固定不变的一些代码,为了提高编程的效率,减少上千个API带给开发人员巨大的精神压力,微软开发出了这么一个类库,注意,这个类库与操作系统本身无任何关系,它只是对API进行了一个面向对象的封装,当然,还给出了一系列编程的框架。使用SDK的方法,使用Visual Studio,通过调用Windows API,MFC你也可以做得出来。MFC把一些固定不变的代码已经写好了,只在编译时候链上,所以我们的代码里看不到WinMain(),而事实上整个程序的运行,和SDK的方式无任何区别,初学者请记住这一点。另,补充一点个人感想,MFC的初衷,带给开发人员更多的便利,我觉得并不太成功。学习MFC所费的力气和最终的所得,并不太成正比。

  "API":Application Programming Interface,应用程序接口
  这个词的出现频率很高,从某种意义上来说,也可以看作是SDK的一个子集。这也是做给程序员的程序,不过一般指用导出函数的方式提供服务的函数库,不包括类库和组件。

  “GDI”:Graphic Device Interface,图形设备接口
  这个是Win32程序下最常用的显示方式,与DirectX、OpenGL处于同一级。在DOS要显示一些东东可不是容易的事,最简单的是调用一些C的图形库函数来实现显示,不过一般也就是些画线,填色,输出几个文字,效果很弱(所以DOS程序界面一般都不怎么样,且实现起来不是一般的复杂),要复杂一点的动画/图片显示什么的,经常要用到的就是硬件中断,调用一些显卡自身的子程序(固化在显卡内的)来做。因为每一个显卡都不同,所以DOS的游戏兼容常常由于显卡的差异而很糟糕。到Windows下大家就幸福多了,Windows将硬件这一层屏蔽起来,用一个表格(Device Context)来代表一个显示,我们要做的就是在这个表格上填好相关参数,然后画上我们想画的东东,然后操作系统会依照这个表格(DC),把相应的显示内容(一般是一块显示内存)传送到指定显卡的指定的显存,再由显卡传给显示屏。我们不再需要与不同的显卡打交通,这是一个十分伟大的胜利!GDI中最常用的是双缓存技术,就是说你可以在内存中创建(也就是复制)一个DC,只不过在这个DC中显示的不再被传送到显示器上。有什么用呢?因为它的各参数是与当前屏幕DC一致的(COPY嘛 ,当然是这个结果),所以它的显示内容可以完整无失真地传送到屏幕DC上。我们通常在内存DC上画图,譬如画一圆,再画一条直线,画完后一次性地传送到屏幕DC上,这样对用户来说屏幕只刷新了一次,可以解决你画一点内容屏幕即刷新一次导致的闪烁问题。当然,双缓冲甚至多缓冲还有很多别的用处,那就要靠自己揣摩了。

  "DirectX"
  通常简称为DX(读音:低叉)这是个很吸引人眼球的名词,读起来就很上口:)。Windows为我们作了许多屏蔽底层硬件的工作,其中DX是最知名的技术之一。操作系统要与各类硬件打交道,特别是多媒体相关的,譬如显卡、声卡、手柄输入、多媒体流的网络传输等等,这些事情如果都自己来弄的话,那就太要命了(这些一般都涉及系统底层,自己也很难做出来)。而DX则正是这么一套操作系统提供的隔离多媒体硬件与程序员的间质,DX自身一般并不实现处理的能力,它是一个标准,要求硬件来满足,好比DX提供一个函数名,硬件来实现函数内容一样。通过它我们可以非常简单而快速地调用硬件提供的各类服务。它主要包括DirectDraw(通过直接访问显示硬件来提供快速的图象处理能力),DirectSound(提供了软硬件的低延迟声音混频和回放,以及直接访问音频设备的能力),DirectPlay (它明确的提供了通用环境连接能力来简化你应用程序之间的通讯服务),Direct3D(DirectDraw的3D版),DirectInput(简化你的应用程序访问鼠标、键盘和操纵杆设备的能力),DX5.0之后又增加了一些(如DirectShow),不再详述。DX一个重要的特点就是你可以通过它直接访问硬件而无需知道硬件的具体细节。譬如DirectDraw,就能够越过内存而直接访问显存,这样的速度将比GDI快很多,不在一个数量级上。补充一点:DX是以组件的方式提供的,而不是通常的导出API的形式。DX SDK的最新版本是9.0

  "COM”:component object model,组件对象模型,一般简称组件
  这是微软为了解决代码重用的一个重要机制。重用代码的最简单办法是源代码重用,把写好的函数和类加到自己当前的代码中,编译即可。简单是简单,敝病却显然的多。另一个常用的方法是单独做成模块,以DLL的形式分发,DLL导出函数或者类,客户程序用动态/静态链接的方法将其加载,这显然比前一种源代码的方法好一些,难度也不大,最为常用。但DLL也有一些不足,最根本的,它不是二进制兼容,DLL版本升级一次就需要与客户程序代码重链接一次,有些时候这几乎是不可能的任务。为了更好地让编程像“搭积木”一样简单,让模块可以完美地配合,完美地替换,COM产生了。COM不是类库,不是代码,不是操作系统的服务,而是一套编程模型,理论上来说,它与语言无关,与操作系统无关,unix下同样可以做COM。COM是一种程序结构模型标准,你做的DLL或EXE在结构上满足这么一个标准,那这个DLL或EXE就是一个组件,它将在该平台上成为二进制兼容。COM主要利用了注册表来登记本模块的信息。客户程序调用时首先查注册表,找到所需组件的位置(这实现了位置透明),然后就用Loadlibrary把它加载进来,这和普通调用没有本质区别,区别在于由于组件特殊的实现方法使得整个过程中用户程序都不知道组件的位置,组件的类的实例化过程,如何销毁,不能直接访问组件的任何实现细节,用户只与组件的几个public接口打交道。这将实现真正的模块之间的独立。对用户程序而言,对于目标组件的认识,除了接口,一无所知。在接口不变的情况下,组件可任 意替换而客户程序不作任何改动,无需编译,仅这一点,在中大型程序的模块集成的过程中就将节约相当多的时间。

  "STL":Standard Template Library,标准模板库
  这是最早由Alexander Stepanov和Meng Lee(蛮像中国人的名字)完成,于1994年提交给ANSI/ISO 标准C++委员会并通过而成为标准C++的一部分。望文生义即可知这是一个代码库标准,不是语法标准。简单地说,STL是以C++中的模板语法为基础建立起来的一套包含基础数据结构和算法的代码库。STL的特点是实现了“类型参数化”,即STL的代码中可处理任意自定义类型的对象,如果不使用模板技术的话,这是一件相当困难的事。也因为这个原因,在最新的java及C#语法中均加入了对模板语法的支持,可见其重要性。另外一个有关STL重要的话题是GP(Generic Programming),泛型。这是与面向对象相并列的另外的一个编程模型,它以模板为基础,弱化了实体类型的差异,简化了编程时问题抽象的模型,提供了更好的封装性和弹性,对于繁杂的面向对象编程毫无疑问是一种解脱,至少是精神上的。GP并不是用来取代面向对象的,而是作为一个有益的补充体,是面向对象很好的合作伙伴。GP是最近几年软件架构的一个研究热点,但国内真正的应用似乎并不多见,这项技术本身还基本处于研究前沿。<>一书对C++中的GP应用有很好的诠释,而这本书对脑细胞的杀伤力之大,也是其它C++书藉望尘莫及的。想知道C++的代码技巧
  可以做到怎样的出神入化吗?不妨看看这本书。

  "ATL":Active Template Library,活动模板库
  这在VC编程下应该算是比较高级的话题了,它集COM和模板技术于一身,带来了极方便的组件编写方法和极高的学习门槛。可以说,进入ATL领域就算是进入了中级以上的编程领域。ATL是为组件而生,它的目的是为了让程序员更方便地编写组件(纯用C++写一个最简单的组件实现一个“Hello World”对初学者来说都是要命的),同时它使用模板技术来类似于MFC一样建立了一个开发COM的框架代码库(模板库),使用该框架及模板库可以相对方便地进行组件开发。ATL中的一个特点就是你自己的类将成为ATL代码库中某些类的父类,这是一件很有趣的事(这也是模板技术的一个特点)。

  "HANDLE": 句柄
  这是一个中文翻译很古怪的字,对初学者来说是百思不得其解的东东。这其实等价于void*(顺便提一下,初学者往往对VC代码中各种古怪的符号、类型标记/宏等百思不得其解,其实它们大多来自基本类型的#define或者typedef,请将光标移到这些符号上(譬如HANDLE),然后按下F12,编译器自会把你带到它的声明处,反复使用几次,你终会见到它的原貌,然后长吁一口气:原来不过如此而已。没用过的初学者请牢记:F12)。很多初学者总想知道一个HANDLE代表一个什么对象,我的建议是不要去理解为某对象,而就是理解为访问某一个对象的入口,事实上HANDLE大多数时候是一个整数索引(标志该对象在操作系统的某表中的位置,就好像一个数组的下标一样),Windows系统核心中主要是几张大表,这样一个整数索引就是标记目标在这个表中的位置,供操作系统访问时查询用。偶而它的确是指向某对象的指针,有时它还携带一些额外辅助信息。总之,我们不要去直接访问它,把访问HANDLE的任务交给操作系统好了,除非你还嫌写程序不累:)。

  "DLL": Dynamic Link Library 动态链接库
  DLL的一个特点就是可以动态加载(顾名思义),即在主程序(我更喜欢称为客户程序)需要该模块时才由操作系统加载到内存。毕竟一个大型应用程序我们经常使用到的功能并不多,这样一些不常用的功能模块(DLL)在程序运行时一般将不被载入,可极大节省内存开销。DLL同时也是目前最常用的分发模块的方法,便于彼此协作。程序中对DLL的调用主要有两种方法:1 针对使用DEF文件导出函数的DLL,使用API函数LoadLibrary(“DLLModuleName" )加载,然后使用GetProcAddress()得到函数指针,进而调用 2 直接将类、函数等导出,客户程序使用同一份头文件声明,加入对应的lib链接库,即可在客户程序中直接使用DLL中的类或函数,无需LoadLibrary。

  "Process": 进程
  进程是一个动态的概念,包括从进程的创建申请,PCB(Process Control Block进程控制块,一般操作系统实现为一个表格(struct))的创建,地址空间的内存分配,模块代码载入并执行,执行完以后进行撤销,整个过程被称为"进程"。在Win32下,一个进程有4G的逻辑空间。但我们也常把它作为静态概念来使用,在Win32下,一个EXE的执行就是一个进程(如果它内部又开了新进程,另当别论)。

  "Thread": 线程
  为了更有效的提高CPU的利用率,更好地实现多任务并发,微软将进程进行进一步分割,实现了CPU任务调度的新对像:线程。一个进程拥有至少一个线程。我们在实现多任务并发的时候通常是建立一个新线程(建立线程的系统开销要小于进程),线程以我们自己的一个函数作为入口,函数执行完毕自动撤销(当然你也可以在执行过程中强制结束该线程)。顺便提一下,在UNIX下并没有线程这个概念,想来是因为UNIX主要是以多进程的并发服务为主(所以它更适合于做服务器),系统运行时通常已经有了太多的进程,所以没有必要再对进程进行细化,因为这样做甚至会降低系统效率(CPU调度不过来),当然,这是我个人的猜想:)

  "C语言"
  到目前为止,C语言应该是传播最为广泛的语言,特别在UNIX的世界里依然扮演着主角的位置,在其余如硬件开发,嵌入式系统(如手机)皆有十分突出的表现,即便在win32平台下SDK的开发中也有一席之地。更主要的是它是大多数国内(国外我不敢说)程序员的启蒙语言,通过它许多人才领会了程序的思维。C最大的特点就是快,除了汇编以外效率可以达到最高,而它的灵活性,对硬件的直访性也完全符合程序员自由的天性。如果说学习别的技术尚有犹豫和徘徊,那么学C只有一句话:相信我,没错的!也有许多人主张可以直接学习面向对象语言,我不太同意。面向对象语言对机器模型的抽象十分容易让程序员迷糊,心中难以建立准确的程序运行时的模型。毕竟我们是程序员,不是用户,我们不能把所有的问题都想当然地交给编译器和操作系统去解决,它们也解决不了。至少学习一门面向过程的语言,才能知其所以然。

  C++
  这是贝尔实验室的又一杰作,同时,也伤透了全球太多程序员的心,脑细胞杀伤力十分之大。C++比大多数初学者想像的都要复杂得多,它基本包括:一个类化了的C语言,模板,标准模板库.很多初学者掌握的C++仅仅只是一个类化了的C语言的一个子集(不相信的话,你不妨看一看<>中的C++代码,看看能理解多少)。更麻烦的是使用C++不得不谈到面向对象的编程风格,这同样比初学者想像的难很多,要有打持久战的准备。而最让我这类C++爱好者忧心的还是它目前在Win平台中的前景,在.net平台上很难找出不用C#而使用C++写新代码的理由:( 。而它的复杂性和目前许多诸如java/C#及一些动态语言(python/ruby)比起来,开发效率显然的低,大有退出上层应用程序开发的趋势。这么一个包含了最多范式的近乎完美的语言,我实在不想放弃。我唯有祈祷在未来C++的路可以走得更远更好一些。

  源代码版本控制
  这是软件开发中一个十分重要的工程手段,几乎是必须的一个Process(过程)。很多作坊式的开发团队在采用软件工程的一些方法的时候,第一个要进行改进或增加的,往往就是这个过程。对初学者学习而言,建议在开始进行实践小项目的阶段即进行源代码版本控制,因为这在以后的工作中,是一定会用到的。  

  源代码版本控制的基本原理如下:
  在服务器端建立该项目的数据库,并保存你选定的项目源文件的第一个版本。客户端任一用户要获得某源文件的修改权利,需进行check out操作。之后客户端一般每完成一个无编译错误的版本想保存的时候,进行check in操作,将当前版本保存在服务器端上并成为最新版本(注意,不是覆盖以前的哟)。任一客户端可以方便地得到服务器上的文件的任意版本(如果有权限的话)。一般还实现了一个重要的功能是版本比较,任一客户端可以利用版本控制工具对某文件的不同版本进行版本比较,它会标记出不同版本的同名文件的不同点,可以轻易地看出版本内容的演化,这一招很常用。 下面介绍一下我接触过的三种版本控制工具(也是国内用得比较多的)

  VSS: Visual Sourcesafe
  这是微软Visual Studio自带的源代码版本控制工具,它最大的特点就是易安装(与Visual Studio集成在一起,装VC/VB的时候就顺便搞定,不用别外费工夫),使用简单(服务器端设置相对容易,一般个人稍加摸索就可以轻松搞定,客户端更是只管check in/out),基本功能完善,版本比较很直观(我喜欢)。它的特点是某人check out了某版本以后,别人将无法对此版本check out,也就是说同一时间只有一个可以修改某一个文件,这样就避免了不同的人对同一文件的修改造成彼此冲突(注:可通过设置服务器端实现多人check out,但几乎不会这样做,因为那样就失去了VSS的一个最重要的功能)。另,VSS可集成于VS环境,但根据我的经验,直接在VC里对版本的check操作,常常不生效,所以最好还是到VSS程序里去进行check操作。补充:单机上也可以使用VSS,这样的好处是在对当前某些文件进行了误操作或大规模地误修改之后,可以恢复到最近的无错误的版本,最大程度地挽回损失。VSS实际应用较普遍,如果你是走Visual Studio路线的话,一定要用一下。

  CVS: Concurrent Versions System
  这个也是一个大名鼎鼎的开源的版本控制工具,主要活跃在UNIX世界。CVS我使用不多,一般而言好像功能比较偏向于命令行方式(UNIX下开发很多人也都使用着命令行方式)。当然,Windows下面也实现了几个版本的CVS,也可以集成于VS,好像还有一个可以挂接在IE上的,我没试过。著名的开源项目管理网站sf.net也是用的CVS,如果你要和全世界的程序员一起协作开发,CVS是必须要安装的。在JAVA的世界里,也是以CVS为主。

  Rational Clearcase
  这个工具就比较上档次了,Rational公司(现在是IBM)的出品,价格昂贵。我最初参加工作的时候用过一小段时间,简单谈一下。这个工具的特点是复杂,安装及设置就十分复杂,我的印像中客户端甚至不得不加入到NT域里面去,导致我在本机的权限都不够,安装新程序都很麻烦,很郁闷(不知道是不是我们公司的相关人员安装设置错了,想来应该是这样,但其复杂性可见一斑)。对使用而言,它有一个功能挺有用的,就是它能够根据你每次check的版本号,自动生成版本树(一个树状图表),你可以清晰地看到版本的演化过程。所以严格地说,像CVS/Clearcase这样的才真正称得上“版本”控制,VSS还太勉强。Clearcase的功能十分强大,我不详述了(我还不想出书),较适于大型软件公司实施软件配置管理时采用。虽然它的名气十分之响亮,但我不知道国内有多少公司在真正使用正版的Clearcase这样的工具,想来应该是十分之少。

  OpenGL
  OpenGL至今颇有一点英雄落寞的味道,这一套标准是实现得如此之好,以至于曾经一度成为游戏界面华丽的标准。它的低落也是一个必然,毕竟在微软的强力打压下鲜有不挫败的。但它曾经能够给微软带来如此的压力,至今也依然在工业界被广泛使用,大多数游戏/显卡依然保留着对它的支持(CS里我喜欢的还是OpenGL)。而它的性能在某些方面与D3D比较,依然占着上风。不幸的是DirectX在不停地向前发展,而它,几乎止步不前了,前景并不光明。OpenGL目前在工业领域应用较为广泛,它的优秀的矢量图的操作性能,华丽的色彩,在专业的图形图像处理领域表现突出。游戏中使用相对以前而言则是越来越少。新近听说微软的最新操作系统Vista对OpenGL进行了极大的打压,不但性能上折扣,支持的版本也只到1.4(最新版本好像是2.0),不知道最后如何收场,拭目以待。

  DirectDraw & D3D
  大凡像样的2维Windows游戏,几乎都是采用此技术来实现显示的。DirectDraw有两种模式:全屏和窗口。其中全屏应用更多一些。在全屏下,DirectDraw有一个十分著名的“换页”技术,即在两个显示页面之间用“交换”来实现显示刷新,这个速度十分地快,只是一个显存内一个指针的交换,比你用BitBlt复制一屏的像素快太多太多,游戏的高效的动画效果大多源于此技术。
  DirectDraw主要用于娱乐领域和一些实时显示要求较高的场合,如医疗图像。D3D是目前大多三维游戏的标准采用,我没钻研过,不敢多言。它的效果嘛,玩玩游戏就知道了:)

  UML:Unified Modeling Language,多译为统一建模语言
  这个语言是一种图形语言,主要是作为设计时建模的一种标准的图形模型,便于程序员与程序员、程序员与客户、设计员与代码员之间的沟通,同时它也帮助设计人员将头脑中的基于程序代码的对程序功能的理解形成文档,便于理清头绪,进行下一步编码的工作。换言之,设计过程的产品,可以表现为一些文本文档,或者一些框架代码,或者一些伪代码,但比较标准通用的,是表现为一堆UML图。UML包括动态图和静态图两大类,其中静态图中的类图最为常用。很多人初学时不知道该怎么做设计,写小软件时常常没有设计过程,其实很简单,把软件的类图画出来就好了。学做设计时未必要找一个像Together或者Rational Rose一样的巨无霸。用一些简单的可以做UML图的工具就好,专门用来画UML图的小工具很多,网上容易找。补充一点:画UML图不要面面俱到,不要什么都画,突出重点方便理解就好,甚至使用不规范的记号也不要紧(当UML的功能是草稿的时候)。

  RTTI: Runtime Type Information 运行时类型信息
  在程序中,当我们得到某一个对象的实例或者指针时,大多数时候并不能直接肯定它的类型(都是继承以及类型转换惹的祸),这个时候,依靠VC4.0或更高版本的编译器提供的RTTI支持,调用库函数typeid()即可在运行时获取这个对象的“类型信息”,在一些动态处理中“类型信息”很重要,获取了类型信息以后,你就可以有十分把握地调用该类型的相关操作,或者类型转换,或动态生成。因其重要性,在JAVA和.net库中借助单根继承和“虚拟机”对此有了更优雅的做法,每一个自object继承的类天然就有了表述自己类型信息的能力(继承的好处),并且容易扩展,现在你需要类型信息的时候,大可直接ask那个对象:tell me, what type are you?它就会告诉你答案。

  debug & release 调试 & 发行
  大家都知道,debug是调试版,release是发行版,区别在于debug版生成的程序中包含大量供调试用的场景代码(不是真正运行需要的),而release一般去掉了这些信息,并进行了某些代码优化,所以release版的程序会比debug版的程序小很多,运行速度也快一些。同时,debug版为了便于调试,往往会对调试使用的诊断代码加上DEBUG一类的宏,使得在release下不对这些代码进行编译。正由于两种版本编译使用的源代码的差异(以及release糟糕的优化),常常使得两种版本运行时产生截然不同的效果,一个正常一个崩溃是大多数人都遇到过的。导致问题的可能性很多,注意事项详见各论坛的诸多精华贴。另,同一个程序如果DLL之间的链接使用了不同版本(譬如EXE是release版,dll是debug版),有时会无法正常运行,所以我一般的做法是每一个DLL针对不同版本使用两个DEF文件,编译生成不同名的两个文件(debug版文件名后加d),调用时各个版本针对自己的版本调用,这在一定程度上可避免混乱。另,release也是可调试的,在工程设置里把调试信息打开即可。

  XP:eXtreme Programming 极限编程

  这是近几年才时兴起来的开发模型,国内大致是01/02年开始有所宣传。

  它主要是针对中小型开发团队在开发时间要求紧、需求不稳定的中小项目(大多数软件项目都是这个情况)时使用。它打破了传统软件工程的框架,非常新巧。譬如整个开发过程中文档很少,大量使用“卡片 (如CRC卡片)”来描述开发计划和内容;没有真正意义上的软件功能规格说明书,取而代之的是一系列可测试的用例;没有独立的设计和测试阶段,它们总是在迭代中增量反复进行;设计:尽可能小和简单;一般没有代码复审(code review),大家共同拥有代码。而它的最显著的一个外在特征是它常使用“成对开发”,即一台机器前坐两个开发人员,共同开发(一个看,一个写),这乍听起来真是蛮有趣的:),它的基本出发点是认为成对开发的效率在一定条件下要高于两个人独立开发的和。不要觉得天方夜谭,在很多项目中,这种做法的有效性已经被证实。

  XP的特点可以用“快、小、灵”来概括,它和传统瀑布模型(自顶向下)的区别在于它使用迭代增量(设计->代码->测试->设计->代码…)的方式。想法很简单:没有什么目标是可以一开始就容易确定的。用爬山来做一下比喻的话,传统的是在山下研究地图,选好一条路线,然后沿着此路前进,XP则是走一走,停一停,看一看,对下一步的方向作出新的选择,在很多时候,这样做会让你选择到更好的捷径。

  ICONIX:
  这个字相信很多人都没见过,我也不知道是什么字拼起来的,作为开拓眼界,我还是提一下吧。这是一种界于XP和RUP(Rational Unified Process)之间的开发模型,换言之,它比XP“大”,比“RUP”要小。它采用了UML的一个子集,特点是用例驱动,保持良好的进度跟踪能力。它的目标是用最短的时间来把用例变成代码。具体来说,这种开发模型相对精简的XP而言,更加强调用例的建立、分析和代码化,用例是其中心地位。

  RUP:Rational Unified Process
  前面已经提到了,相信你已经感觉出它是一个丰富的软件开发模型。这是由IBM提出来的软件工程模型,它使用完整的UML图,对开发的各阶段(需求、设计、代码、测试、维护)均有十分完善而复杂的标准,就不详述了。RUP本质上是迭代式开发,在每一次迭代中均完成以下四个阶段:初始阶段(inception)、详述阶段(elaboration)、构建阶段(construction)、转换阶段(transition)。

  CMM:Capability Maturity Model 软件成熟度模型
  这是卡内基*梅隆大学软件工程研究所(我的专业正是软件工程,所以这也成为我心目中的圣地)的一大力作,一度曾形成了席卷全球软件开发的CMM浪潮。CMM分为五级,大多数软件企业都处于第一级,而得到第五级认证的全球也没有多少,国内去除掉挂羊头卖狗肉的,也是寥若星辰(嗯,比星辰是寥多了)。所以CMM实施一般是从第二级开始,能做到第三级的都是颇有实力的软件公司了。CMM是以Process(过程)为中心的模型,从二级始每一级都有几个Key Process(关键过程),每一个KP又分为若干Key Active(关键活动)。CMM的实施一般不能越级实施,并且每一级的实施通常都要一年以上,所以要达到较高等级是一级很困难的事。另,CMM不仅可用于较大规模公司,同样也可实施于小公司,小项目组(这是很多人所不知道的)。实施视具体情况等级之间可交叉,譬如实施时采用二级的某些KP再加上三级甚至四级的KP,但你只有实施了所有二级的KP,你才能也只能通过二级认证,即便你采用了某些四级的KP。CMM最新发展成果是CMMI(Integration),这主要是新考虑了软件与非纯软件因素的关系(譬如系统),以及团队之间的协作问题。CMM在国内的发展似乎有点走向ISO同样的道路,这实在不是一个好消息。

  Callback Function: 回调函数
  在侯sir的<<深入浅出>>中一开始就提出了这个概念,大概的提法是说回调函数是操作系统调用而你永远不要去调用的函数。这个提法让初学者有点望而生畏,以为是一种多么高深而难以领会的系统底层的核心技术。其实不然,这个技术本质很简单,而且很常用。它实质就是函数指针的基本运用(如果不知道什么是函数指针的话,翻翻书)。在一个模块中,有时想让一部分功能由其它模块实现,譬如说一个做显示的模块,它只想实现显示的资源配备,画面的刷新,缩放等控制功能,而把画具体实体(譬如圆、多边形,都可以有很多种不同效率的实现方法)的代码由别的模块来实现,怎么办呢?用函数指针。在自己的类中放一个画圆的函数指针,使用时由外部为这个函数指针赋值(其实就是指向了一个外部的函数),在自己的代码中直接调用这个函数指针来画就可以了(本模块完全不知道外部模块是怎么画圆的)。那个外部的函数在这里就是回调函数!

  在很多系统API中就使用了这种函数回调的方法,让我们开发的代码实现可以嵌入到API的代码实现当中,其实我们就是传了一个函数地址给它而已。换句话说,这些API搭好了某些运行的代码框架,我们来为它具体实现。

  XML: Extensible Markup Language 可扩充标记语言
  也许你还在为选择.net和j2ee而徘徊不前,如果是这样的话,不妨先着手学一下它们所共通的一个基础:XML。有了HTML为什么我们还要XML?很简单,HTML重在表现文本/图片以及一些多媒体内容,它很难表达数据,因为它的标记是固定的,而数据类型千千万,根本无法描述。.net和j2ee都要解决一个信息传输格式标准化的难题,这个格式要能承载文本/数据,最好还能描述程序接口,同时又应该像HTML一样简单,具有通用性,能够在HTTP下很好的运作。在这种要求下,XML产生了。它的特点正如其名,和HTTP一样,它也是一种标记语言,但是它的标记不是固定的,是可自定义(也就可无限扩展)的,这些自定义标记能够很好的描述数据类型以及对应的数据内容(乍看起来很像数据库表的定义)。除此以外,XML还可以描述程序接口,所以XML可以方便地与网络程序构件(COM、EJB等)直接交互。由于它也是一种ASCII文本流,所以与当前的HTTP兼容,在当前的internet上畅通无阻(这很重要)。有了以上功能,XML就名副其实地成为了新一代互联网技术的标准信息载体,在.net和j2ee的网络架构中,各种“构件”的信息交互都交给了XML,可谓任重而道远。

  XML我自己没怎么写过,单就学习上的经验而言,感觉语法上比HTML更琐碎一些,小细节更多,没那么容易速成:) 好在根本同源,有HTML基础甚至WEB开发基础的,学起来也很轻松。

  Java2:
  这是近几年最吸引大众焦点的语言,在Web开发,网络平台,移动开发的世界里发光发热。你可以不用java,但你不可以不了解java,毕竟这是一个极大且丰富的软件开发领域。有些没使用过java的VS阵营里的人可能还不明白java2里的那个2是什么意思,容我先解释一下。Java最初正式推出1.0时,并没有受到如此多的好评,受到颇多责难,于是它不断地推出新版本来完善自己,其中变化显著的一个版本是1.2(我没记错吧),Java的每一个新版本除了语法上的更新,还有一明显的标志,那就是JDK(Java Development Kit,就是Java自带的一套SDK)的更新,版本1.2以后的java为了在宣传上与以前的java相区别,便被称为java2。目前用得比较多的jdk是1.3/1.4 ,最新的JDK是1.5(代号tiger)。java开发的IDE国内主要以JBuilder为主,另外就是在开源领域如雷贯耳的Eclipse,而sun也力推自己的开源java IDE:Netbeans(从sun的网站上可下载,免费)。Java运行是虚拟机机制,相当于在操作系统上增加了一个软操作系统,源码被编译成一种字节中间码,由虚拟机解释执行,只要有对应的虚拟机,java程序就可以在该操作系统上运行,这就是java号称的一次编译,到处运行的由来。而附带而来的不可避免的性能问题也让Java难以成为桌面程序开发的主流。补充一下:对初学者学习而言最好的Java IDE我推荐使用JCreator,这是一个C++写成的IDE,几MB的大小,比Eclipse快十倍以上的启动速度,对初学者带来极大的便利。

  J2EE:
  Java实际上又被分为3类:J2EE/J2SE/J2ME,不同类分别对应不同的JDK,J2EE针对企业平台开发,J2SE是标准版,J2ME针对移动平台开发。J2EE现在实在是热得烫手,我前不久翻了一下程序员早期的杂志,发现在第一期创刊号里(2001.1)已经有了j2EE方面的讨论,现在已经是2004.6了,你对它的认知又多了多少?J2EE不是一种单纯的技术,而是一种体系架构以及组成该架构的诸多标准。企业平台开发和桌面/简单Web数据库开发有很大的不同,它的程序规模往往很大(不是一个或者几个EXE可以搞定的),用到的往往是海量的数据库和海量的通信,并且常常是不可中断的,这些特殊性都使得企业平台开发更多地去关注架构的问题。而我们写一个熟悉的java客户端程序,或者消息处理中间件,又或者数据库处理程序,都只是这样一个架构里的一小部分。J2EE是很宠大的,所以请不要写了几个EJB(这是java世界里的构件,概念上大概是类似于COM)的例子程序就感觉自己精通j2EE。

  J2EE中传递消息时往往引入了一个被称作消息管理器的中间件,在服务器端使用EJB的容器来管理和调用EJB。在J2EE中一个重要的概念是Transaction(事务)处理,事务的概念最早广泛应用于数据库技术。这实际上是一个封装了很多操作的单元,它的作用是中间任何一个操作失败,可以自动依次整体撤销,所以一个transaction就是操作成功/失败的最小单元,不存在一个transaction只成功了部分操作的情况。

  在企业服务平台开发中比较知名的有一个叫BEA公司(这是一家不错的公司,应该知道它的名字),它的产品是Weblogic。

  .net
  .net是微软为下一个十年准备的技术,你呢?.net也是一种平台技术,而不是单一技术。它主要分为.net运行时平台(对应java的虚拟机)和.net类库(对应java的jdk)。目前只有Windows2003是天然集成了.net运行时平台的操作系统,所以如是你写的.net程序想要在别的操作系统上运行,该操作系统必须先安装.net平台,这是一件蛮烦人的事,也是为什么到目前为止,还没有太多的人改用.net来写程序(尽管可极大提高开发效率)。希望Longhorn的出现可以扭转这一现状。那我们就终于可以和MFC这样过时的框架类库说再见了,一大快事。

  .net采用了很多最新的技术和思想,对走VS路线的人来说(特别是有COM概念的),学起来相对轻松且很过瘾,前人推荐的“.net框架程序设计“和”.net本质论“都是很好的书。当然,看它们之前你最好基本掌握一门.net语言,譬如C#,掌握语言对我们来说是最easy的。

·攻击前奏(1)

    最近刚出了一部新片“防火墙”,这是一部有关黑客的电影,所谓“外行看热闹,内行看门道”,从剧中我们可能看到一项黑客技术的威力——那就是社会工程学!由于“防火墙”的启发,我对下载软件“迅雷”进行分析,成功捕获了大量的肉鸡!

    一、攻击前奏

    迅雷是一个集成了P2P功能的下载软件,下载速度快,提供了用户注册功能,在线时长达到一定时间的用户可以在“雷区”发布资源,共享给其他用户下载(如图1)。


图1

    首先我们需要准备一个木马文件用于上传到雷区,由于雷区发布的资源大部分都是压缩包文件或者视频,因此可以考虑制作一个自解压运行木马的压缩包文件,也可以将木马与其它程序捆绑在一起,然后打包压缩。不过为了更具攻击隐藏性,同时为了说明后面社会工程学的利用,笔者在这里制作了一个Realplayer视频木马。

    这个视频木马利用了RealPlayer的“.smil文件处理缓冲区溢出漏洞”,当别人播放时会造成溢出,我们就可以连接控制对方的主机。首先将溢出程序“real.exe”下载,在“运行”中输入CMD打开命令提示符窗口,进入溢出程序所在的文件夹。溢出程序的命令格式为:“real.exe<生成文件名>”;
其中生成的文件名是.smil后缀的视频文件,这里直接输入“real.exe美女的激情视频.smil”,命令执行后提示:

    "File written.Binds a shell on port 13579.Open with realplayer to exploit."(如图2);
程序执行后已经生成了一个溢出媒体文件“美女的激情视频.smil”,只要存在漏洞的Realplayer程序打开此媒体文件,就会造成溢出并开放13579端口。


图2

·窃取迅雷帐号

    二、窃取迅雷帐号

    首先我们先将这个视频上传到任意一个空间,比如这里笔者上传到了Google的个人主页空间里面。然后用迅雷将视频下载到本地,在迅雷的下载任务框中,可以看到已下载的文件列表“雷区”栏中有一个“发布”链接。点击菜单“雷区”→“进入雷区”,打开迅雷帐号登录对话框,输入自己注册的用户名和密码,登录后在左侧的“雷友信息”中可以看到自己的积分和等级。如果是少校军衔就可以直接点击“发布”链接,或者点击右键,选择弹出菜单中的“发布到雷区”命令,将刚才下载的美女视频发布到迅雷的公共资源区(如图3)。


图3

    小提示由于迅雷官方为了防止发布的资源混乱,因此只有少校以上军衔的雷友可以点击“发布”链接发布资源。如果你的军衔低,就要破解一个少校用户来发布资源了。

    在程序界面右侧的“热门推荐”中点击“更多”按钮,用IE打开雷区资源发布页面,在页面中显示了公共下载资源类别以及每个分类下详细的资源信息(如图4)。在资源信息中找到“资源来源”栏,可以看到发布资源的迅雷用户帐号,这些帐号肯定都是少校以上级别的。只要盗取其中的某一个帐号,就可以将视频木马上传到雷区了。


图4

    1.弱口令破解法

    许多用户在注册帐号时为了图方便,往往将密码设置为“111111”或“123456”之类的弱口令,因此我们可以用猜测密码的方法破解列表中的用户帐号。可以一个一个的试,笔者只用了十多分钟就测试到有4个用户使用的密码为“123456”。

    2.密码找回法

    一些用户在注册时设置了密码找回功能,这类用户的密码往往设置得较为安全,不易猜测。不过如果你有细心与想象力,密码找回功能也可以破解出密码。以笔者为例,在用户列表中看到有一个名为“anshiwei”的用户,很明显示这串字符肯定是用户真实姓名的汉语拼音(如图5)。于是先尝试用“123456”登录,结果没有成功。再点击登录框中的“忘记密码”按钮,选择“回答问题找回密码”方式。点击下一步,输入要破解的用户名“anshiwei”,弹出问题回答对话框。问题是“你的姓名是什么?”(如图6),很明显可以利用该用户姓名的汉语拼音推出汉字来——不是“安世伟”,就是“安世威”、“安寺伟”之类的,反正总不可能是“俺是萎”吧?呵呵!回答问题只能三次,如果答案错误的话,可以返回登录窗口,再次使用“忘记密码”功能重新猜测。


图5


图6

·发布木马、锁定肉鸡

    三、发布木马

    用破解来的帐号登录后,就可以发布视频了,因为生成的.smil木马体积比较小,所以我就用WinRAR将视频打包压缩,然后再将一个真实的视频文件改名成“登录我们的视频网站.html”,将其添加到压缩包中,这样压缩包的体积大小看起来就正常了。然后在迅雷中选择该文件,点击“发布”,在弹出的发布对话框中设置各种信息,点击“确定”按钮即可将视频木马发布到雷区了(如图7)。
图7

    四、锁定肉鸡

    因为发布视频的都是使用迅雷时间较长的用户,视频来源相对是比较可靠的,加上我们为视频起的名字很有诱惑力,因此刚才发布的视频很快就会被别人下载观看。别人打开“美女的激情视频.smil”文件后,就会造成溢出并打开系统13579端口。直接使用Telnet就可以登录控制远程主机,命令为:“telnet 远程主机IP地址 13579”。

    可是我们这里是采用溢出的攻击方式,而不是让木马自动反弹连接,那么我们该如何才能得知远程主机的IP地址呢?稍微细心一点,到资源发布页面中查看一下别人对该视频的回复,就可以看到下载者的IP地址了(如图8)。拿出扫描器扫描一下子相应的IP段开放了“13579”端口的主机,那台主机就是你的小肉鸡啦!——当然,如果你发布的是其它反弹木马之类的,那么寻找控制肉鸡就更简单了!
real溢出程序 下载地址:http://download2.77169.net/200503/050311realplay.rar


图8