2006年10月31日

请把我在你们叶子上的连接修改为http://www.gfrog.net

对此给您带来的不便,我深表歉意.

顺路说,无意中路过这里的朋友们,从各种叶子跳到这里的朋友们,以及各种不认识我的朋友们,

请在你们的收藏夹里添加上http://www.gfrog.net,或者在你的叶子上加上http://www.gfrog.net,

顺便到http://www.gfrog.net 这里踩个脚印,告诉青蛙有一个人来过青蛙的池塘吧,谢谢大家.

Update: 2010-05-30

亲爱的同学们,如果你还能看到这篇日志,那么请注意哦,青蛙的主页地址改为gfrog.net,之前的cn域名已经彻底被废弃,望周知。

2006年09月29日

http://www.gfrog.net/

特此公告,欢迎访问.

2005年10月01日

无相 03-09-20 00:09

关于3322.org动态域名问题
 我是通过ADSL MODEM自带的路由功能上网,已经配置好端口映射,我在WINDOWS下的试过,能够正常使用。我下载了3322的linux客户端,将qdns.conf中设置成interface=eth0,然后ping一下,晕,解析的竟是192.168.这样的私有地址,请问该如何配置?3322支持吗?


ppyy 03-12-01 10:07

更新动态域名最方便的办法(对3322有效)
 
3322的更新还有更加简单的办法,连客户端都不用安装,也不用配置文件,不用知道IP,使用lynx(一般的Linux, BSD都自带), 就可以了, 使用方法:

lynx -mime_header -auth=user:pass "http://www.3322.org/dyndns/update?system=dyndns&hostname=myhost.3322.org"



无相 03-09-20 00:09

关于3322.org动态域名问题
 我是通过ADSL MODEM自带的路由功能上网,已经配置好端口映射,我在WINDOWS下的试过,能够正常使用。我下载了3322的linux客户端,将qdns.conf中设置成interface=eth0,然后ping一下,晕,解析的竟是192.168.这样的私有地址,请问该如何配置?3322支持吗?

 

huzi 03-09-20 08:54

你相当于是在内网上网
 
你用带路由功能的猫上网,你的电脑用的是私有IP。当你用3322的客户端的时候,它更新的是你的电脑的IP地址,所以当你访问你的网址的时候,是一个私有IP,当然不行了。解决办法是关掉它的路由功能,使用pppoe拨号上网



ppyy 03-12-01 10:07

更新动态域名最方便的办法(对3322有效)
 
3322的更新还有更加简单的办法,连客户端都不用安装,也不用配置文件,不用知道IP,使用lynx(一般的Linux, BSD都自带), 就可以了, 使用方法:

lynx -mime_header -auth=user:pass "http://www.3322.org/dyndns/update?system=dyndns&hostname=myhost.3322.org"



 



 



北南南北 03-12-01 10:35


GOOOOD,成功

我们可以把这句写到一个文件中,比如我们申请到的用户名是sirlinux,密码是222222,申请到的三级域名是linuxsir001.linuxsir.org

所以根据ppyy兄的办法,我们可以在这个文件中的内容是如下的:

lynx -mime_header -auth=sirlinux:222222 "http://www.3322.org/dyndns/update?system=dyndns&hostname=linuxsir001.3322.org"

然后保存为一个文件名,比如文件名为linuxsir001,保存后,我们要把这个文件的权限设置为755

#chmod 755 linuxsir001

然后执行
#./linuxsir001

多谢ppyy兄,不错的方法。



allwin 03-12-05 17:08

可以用3322提供的客户端嘛
对于局域网用户,可以把port该成eth0



565285 03-12-19 21:01

真不明白。这可以用在内网用户上吗?
我也是通过ADSL路由方式 上网的。,在XP下我通过ADSL端口映射,再加上花生壳客户端软件搞定的动态域名的!!
可惜花生壳没 有LINUX版的!



bluejesica 03-12-21 00:43

好贴子,不果port改成eth0就可以了



fanf 03-12-28 23:52

那么我有个问题:我怎么在adsl 断线重新连接以后能自动运行此命令?



victor2002 04-01-02 18:18

3322的linux客户端软件好象有点问题。用科迈网的吧,www.dns0755.net 他的公网类型是免费的(科迈公网免费二级域名xxxx.dns0755.net)。按楼主的上网方式在linux及windows下都OK。



adminxp 04-12-12 07:01

www.chanix.net

Signpost动态域名使用步骤

* 在本站下载 Signpost 客户端的最新版本,客户端有 Windows 版和 Unix 版两种,请您根据使用的操作系统下载正确的版本。在有些下载站点提供的版本是以前的测试版,该版本已经不能再使用,请大家到本站下载最新的版本。
* 注册用户,可以在客户端程序点"申请用户"按钮或者到 http://www.chanix.net/console 点注册按钮。在注册用户前请大家先看看法律法规,同时提供的资料必须真实有效。本站实行严格的用户管理,发现有违轨行为,将删除用户,严重的将向相关部门举抱。
* 登录用户中心,点击 社区服务->动态域名服务 注册您希望使用的域名。
* 运行 Signpost 客户端,如果运行正常的话,系统托盘中的灯是绿色的。这时,别人就可以通过你注册的域名来访问您的机器了。
* 接下来,就要安装相应的服务器软件了,具体要看你准备提供些什么服务。一般我们会安装 web、ftp、email 等服务器。当然,因为机器是您自己的,您可以不受限制的提供你希望提供的任何服务。比如,我机器上就装了 CS 服务器,闲来无事就和朋友一起杀两把,做几回靶子 T_T 。

Signpost的DNS服务器地址

ns1.chanix.net 202.103.190.182
ns2.chanix.net 202.103.190.183

Signpost支持的操作系统
MS WINDOWS98
MS WINDOWS2000 PROFESSIONAL
MS WINDOWS2000 SERVER (推荐)
MS WINDOWS2000 ADVANCEDSERVER
MS WINDOWS ME
MS WINDOWS NT4 (SP4以上)
MS WINDOWS XP PROFESSIONAL/HOME/MS WINDOWS SERVER 2003

Unix 版本,包含 OpenBSD、AIX、FreeBSD、Linux 版本

***********************************************************************




Dragonsoar 04-12-12 17:08

用lynx这个办法不错,觉得比科迈网的快。
顶一下。




moofeng 04-12-13 17:05

Re :可惜花生壳没 有LINUX版的!

花生壳的论坛里有网友做的linux版的,可以去看看。



linfeng.CN 04-12-22 21:22

但是 如何 让它 自动执行那 我指的是 每隔10分钟检查一次的那种!



yuri-master 05-01-31 13:20

我还有更好的要加。
#echo "lynx -mime_header -auth=sirlinux:222222 "http://www.3322.org/dyndns/update?system=dyndns&hostname=linuxsir001.3322.org" /sbin/qdns
#chmod a+x /sbin/qdns

#vi /etc/ppp/ip-up
把"/sbin/ip-up"加到exit上面一行
这样每次重新不好后都能更新一次。

上面讲了不少基础性的概念

https://www6.software.ibm.com/developerworks/cn/onlinecourse/tech/l-cluster/main.swf

2005年09月29日

集群的概念容易和一些概念(SMP 、NUMA、MPP、分布处理)相混淆,其主要区别在资源被共享和复制的级别不同。它们是按SMP、NUMA、MPP、集群、分布处理从最紧密到最松散的排列。

  SMP(多处理系统):这种系统是在一台计算机里有多个CPU,CPU之间的地位是平等的,它们共享内存空间和I/O设备。其工作方法是由操作系统负责将任务分解成多个并发进程,然后让其在不同的CPU上运行。

  NUMA(非统一内存存取):这种系统可以让多处理计算机的CPU比SMP更高效地共享本地内存,CPU可以更快速地存取单一的内存区域,不过如需要也可以用间接方式存取其他区域的内存,这种方法是让某些CPU在给定范围的物理内存中有更大的优先使用权。

  MPP(巨型并行处理):这种系统的节点都有自己的CPU,并有自己的专有资源。此种结构相对独立,但各个节点一般没有完全存取I/O的能力。

  集群:集群系统是由独立的计算机组成,但有控制管理工具统一管理。

  分布处理:它是比我们要构筑的集群系统更松散的连接,一般是任务在不同的地方完成,没有可以作为整体管理的单一实体。

  以上的聚合方式有紧有疏,它们都有自己的适用范围,这里就不多说了,有兴趣可自己找些资料看,这里只是想让大家了解它所处的位置。

实现负载均衡的方法

  集群的目的是共享和高效地利用资源,提供大型运算,提供负载均衡分配请求压力以及出现故障时能够进行切换实现高可用性。

  限于篇幅,本文只对负载均衡的实现做些介绍(针对TurboLinux Cluster Server)。通过对相关软件的分析,实现集群负载的功能是通过流量管理实现的,具体有这样几种实现方法:直接路由(Direct forwarding)、网络地址转换(NAT)、隧道技术(Tunneling)。

直接路由(Direct forwarding)

  当参与集群的计算机和作为控制管理的计算机在同一个网段时可以用此法,控制管理的计算机接收到请求包时直接送到参与集群的节点。优点是返回给客户的流量不经过控制主机,速度快开销少。

网络地址转换(NAT)

  这种方法可能大家较熟悉,地址转换器有能被外界访问到的合法IP地址,它修改来自专有网络的流出包的地址,外界看起来包是来自地址转换器本身,当外界包送到转换器时,它能判断出应该将包送到内部网的哪个节点。优点是节省IP地址,能对内部进行伪装;缺点是效率低,因为返回给请求方的流量经过转换器。

隧道技术(Tunneling)

  这种方式是在集群的节点不在同一个网段时可用的转发机制,是将IP包封装在其他网络流量中的方法,为了安全的考虑,应该使用隧道技术中的VPN,也可使用租用专线。

  集群所能提供的服务是基于TCP/IP的Web服务、Mail服务、News服务、DNS服务、Proxy服务器等等,下面我们将就具体的产品TurboLinux Cluster Server 来实现一个进行负载均衡集群系统,用于提供Web和FTP的服务。

四台服务器的负载均衡实例

  所提供的服务:Web、FTP。

       系统的实现目的:做一个较完善负载均衡的系统,以便能用到其中的较多的功能。

  采用设备状况:使用四台服务器,其中3台装TurboLinux Cluster Server,1台安装Windows 2000 Sever。

系统安装

  1.在两台服务器上安装TurboLinux, apache和wu-ftpd也要安装,因为集群要提供这种服务,安装完后重启,挂接光驱在目录/mnt/cdrom下,执 行./TLCS-install,然后按提示完全安装。

  2.在一台服务器上安装Windows 2000 Server,要安装Internet Information Server 5.0。

系统配置

  1.设置各台服务器的IP地址、子网掩码、路由等,调通网络,将一台TurboLinux服务器设置 成DNS服务器,使其能够正向解析和反向解析。服务器名此例为 pc1,域为test.com。

  2.配置Cluster Server。执行Turbolinux clusteradmin,设置情况如下(注:箭头连接的是选单选项,箭头所指为下级选单,最后冒号后为设置情况)。

  ClusterServer Configuration→Cluster Services→Application Stability Agents:

  (1)http为默认的服务,不用设置

  (2)ftp—-/usr/lib/ftpAgent

  ClusterServer Configuration→Cluster Services→Service Settings:

  (1)http,80:TCP,sticky

  (2)ftp,21:TCP,ftp

  ClusterServer Configuration→Servers Configuration:

  (1) pc1 (pc1.test.com),direct,ping

  (2) pc2 (pc2.test.com),direct,ping

  (3) pc3 (pc3.test.com),direct,ping

  (4) pc4 (pc4.test.com),direct,ping

  ClusterServer Configuration→Advance Traffic Managers:

  (1)Advance Traffic Manager System: pc1.test.com

  (2)Advance Traffic Manager Setting: 默认值

  ClusterServer Configuration→Virtual Severs:

  (1)主机为:pc1.test.com

  (2)sendmail:master@pc1.test.com

  (3)Server pool name: ServerGroup1

  ClusterServer Configuration→Globle Settings:

  网络设置:netmask 255.255.255.0

配置集群各接点

  因为TurboLinux Cluster Server 本身能被工具自动同步,所以只需配置Windows 2000 Server:

  开始→设置→控制面板→添加新硬件→下一步→添加/排除设备故障→添加新设备→否,我想从列表选择硬件→其他设备→Microsoft:Microsoft Loopback Adapter→完成。

  桌面上右键单击“网上邻居”→属性→TCP/IP→设置IP地址、缺省网关,子网掩码(注:先设成:255.255.255.0)。

  开始→运行→regedit→找到注册表中跟Microsoft Loopback Adapter相关的项,将子网掩码改成:255.255.255.255。

  配置系统以便运行合适的服务、并配置适合控制管理器管理的配置,以便可在控制管理器中使用。

  在管理选单中执行内容同步

  选tlcs_content_sync,输入密码,将复制控制管理计算机中的服务内容。

  在管理选单中执行设置同步

  选tlcs_config_sync,输入密码,将复制控制管理计算机中的设置。

  现在已经可以进入运行状态,可将客户端连接在服务器的交换机上,客户端可以请求Web和FTP服务,需要查看运行情况可以用控制台从https://pc1.test.com:910管理。

  在计算机技术中集群负载平衡是自成体系的,目前它是一个热门技术也是一个高端应用,Internet/Intranet中使用集群负载平衡方案的地方十分广泛,尤其是大中型网站都难脱离这种技术,直接路由(Direct forwarding)、网络地址转换(NAT)、隧道技术(Tunneling)都会因需要而被采用。它在网络中的作用和被人们重视程度都是很高的,如果你也感兴趣的话,不妨也来试试。

2005年09月27日

息来源:www.csdn.net
作者blog:http://blog.csdn.net/i_like_cpp/


C语言的学习,一般的方式是,先学C,然后是C++,最好还要有汇编语言和微机原理基础,然后才是Visual C++。这样的方式,对学习者来说,要花费很多时间和耐力。而在学校教学中,也没有时间深入学习Windows编程的实用技术了。

  其实,具有了C语言基础后,再有一些基本的C++类的概念,就可以直接学习Windows C编程了。

  一、走近Windows C语言

  很多语言都把显示一个“Hello,World!”做为第一个入门程序, C语言的第一个程序是这样的:

#include<stdio.h>
main()
{
 printf(“Hello,World!”);
}

  如果把main函数写成带参数的main函数,应该是:

#include<stdio.h>
main(int arge,char *argv[])
{
 printf(“Hello,World!”);
}

  Windows C的第一个程序和这个程序在形式和原理上都是一致的,只是有两点不同:

  1. 主函数接收的形参不只是命令行中的字符串的个数和字符串的首地址。

  2. C语言的很多函数在Windows C中都可以继续使用,但象printf()屏幕显示等函数就不能继续使用了。因为Windows是多任务操作系统,屏幕已不再为某一个应用程序所独有,Windows C应用程序要显示字符串,需要使用Windows提供的API函数,开自己的窗口

  下面是一个最简单的,显示“Hello,World!”的Windows C程序:

#include<windows.h>
APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
 MessageBox(NULL,"Hello,World!","第一个Windows C程序",MB_OK|MB_ICONASTERISK);
}

  主函数的形参有四个:

  1) Hinstance:接收程序运行时当前实例的句柄;
  2) HprivInstance:前一个实例的句柄;
  3) LpCmdLine:程序命令行指针;
  4) NcmdShow:一个用来指定窗口显示方式的整数。

  这几个参数的使用我们会在深入的学习中介绍的。

  显示Hello,Word!字符串,我们使用了一个MessageBox函数,这个函数会在屏幕上显示一个对话框,它的原型是:

int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UNIT uType)

  四个参数分别是:

  1) HWnd:父窗口的句柄;
  2) LpText:要显示字符串的指针;
  3) LpCaption:对话框标题字符串的指针;
  4) UType:显示在对话框上的小图标的类型。

  使用这个函数要包含windows.h头文件。

  调试一下,怎么样?窗口上弹出了一个“第一个Windows C程序”对话框,上面有一行字:“Hello,World!”。

  世界真的很美好啊!!

  深入编程:

  在C语言中,函数的声明,如果没有指明返回值类型,缺省值为void,这个程序的主函数就没有返回值。不过,在Windows编程时,我们最好养成个好习惯,指明函数的返回值类型,因为在C++中,函数返回值类型是不可以缺省的。而我们在Windows C编程时,还是会用到C++的一些概念,这样做,有利于以后深入地学习。

  规范一点的程序应该是这样的:

#include<windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
MessageBox(NULL,"Hello,World!","第一个Windows C程序",MB_OK|MB_ICONASTERISK);
return 0;
}

  这里,我们声明的类型为int型,并且返回一个值0,这样的函数就可以使用在复杂一点的函数调用中了。

  在这一节中,我们有几处都提到了句柄的概念,句柄和指针的概念不同,它是作为操作系统内部索引表中的一个值来使用的,这样可以防止应用程序直接访问名对象的内部结构,体现了Windows资源管理的优越性。譬如说,一个窗口找开之后,好对应内存中的一个内存块,这个窗口所在的内存快地址往往会由操作系统做动态的调整,但其却不会随之变化。不过,通过它可以访问这个窗口,所以在使用的时候,可以把它当做指针一样看待。
  二、 获取本地计算机的主机名和IP地址

  和C语言一样,函数是Windows C编程的最基本的单位。不过,Windows C主要使用API函数,而网络编程则主要使用Winsock提供的API函数。

  Winsock是90年代初,为了方便网络编程,由Microsoft联合了其他几家公司共同制定的一套WINDOWS下的网络编程接口,它是通过C语言的动态链接库方式提供给用户及软件开发者的,主要由winsock.h头文件和动态链接库winsock.dll组成,目前有两个版本:Winsock1.1和Winsock2.0。

  在Win32平台上,访问众多的基层网络协议,Winsock是首选接口。

  用Visual C++6.0编译Windows C程序,使用Winsock API函数时,首先要把wsock32.lib添加到它的库模块中,否刚在链接的时候,会出现“error LNK2001”错误。添加wsock32.lib的具体步骤是:打开工程菜单,选择设置,在弹出的Project settings对话框中,点击link选项卡,然后在对象/库模块文本框中添加wsock32.lib。

  最简单的网络编程是获取本机的主机名和IP地址,这个程序使用了WSAStart()、WSAClenaup()、gethostname()、gethostbyname()四个winsock API函数,这四个函数的功能和使用方法介绍如下:

  1. WSAStartup():

  【函数原型】

int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);

  【使用说明】

  每一个使用winsock的应用程序,都必须进行WSAStart函数调用,并且只有在调用成功之后才能使用其它的winsock网络操作函数。

  WVersionRequired:<输入>表示欲使用的Winsock版本,这是一个WORD类型的整数,它的高位字节定义的是次版本号,低位字节定义的是主版本号。

  LpWSAData:<输出>是一个指向WSADATA资料的指针。这个资料我们一般不使用。

  返回值:调用成功返回0;否则,返回出错信息。

  2. WSAClenaup():

  【函数原型】

int PASCAL FAR WSACleanup(void);

  【使用说明】

  winsock使用后,要调用WSACleanup函数关闭网络设备,以便释放其占用的资源。

  3.gethostname()

  【函数原型】

int PASCAL FAR gethostname (char FAR * name, int namelen);

  【使用说明】

  该函数可以获取本地主机的主机名,其中:

  name:<输出>用于指向所获取的主机名的缓冲区的指针。

  Namelen:<输入>缓冲区的大小,以字节为单位。

  返回值:若无错误,返回0;否则,返回错误代吗。

  4.gethostbyname()

  【函数原型】

struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);

  【使用说明】

  该函数可以从主机名数据库中得到对应的“主机”。

  该函数唯一的参数name就是前面调用函数gethostname()得到的主机名。若无错误,刚返回一个指向hostent结构的批针,它可以标识一个“主机”列表。

  Hostent结构定义如下:

Struct hostent
{
char FAR * h_name;
char FAR FAR ** h_aliases;
short h_addrtype;
char FAR FAR ** h_addr_list;
}

  其中:

  h_name:<输入>主机名地址(PC)。
  h_aliases:一个由主机备用名组成的空中止数组。
  H_addrtype:返回地址的类型,对于Winsock,这个域总是PF_INET。
  H_lenth:每个地址的长度(字节数),对应于PF_INET域应该为4。
  H_addr_list:应该以空指针结尾的主机地址的列表,返回的地址是以网络顺序排列的。

  其中,h_addr_list[0]存放的就是本地主机的4个字节的IP地址,即:

  h_addr_list[0][0].h_addr_list[0][1].h_addr_list[0][2].h_addr_list[0][3]

  一个简单的用消息框显示主机名和IP地址的源程序如下:

#include<winsock.h>

int WSA_return;
WSADATA WSAData;

HOSTENT *host_entry;
char host_name[256];
char host_address[256];

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
 WSA_return=WSAStartup(0×0101,&WSAData);

 if(WSA_return==0)
 {
  gethostname(host_name,256);
  host_entry=gethostbyname(host_name);
  if(host_entry!=0)
  {
   wsprintf(host_address,"%d.%d.%d.%d",
    (host_entry->h_addr_list[0][0]&0×00ff),
    (host_entry->h_addr_list[0][1]&0×00ff),
    (host_entry->h_addr_list[0][2]&0×00ff),
    (host_entry->h_addr_list[0][3]&0×00ff));

   MessageBox(NULL,host_address,host_name,MB_OK);
  }
 }
 WSACleanup();
 return 0;
}


  深入编程:

  前面显示IP地址的时候,我们使用的是消息框,规范一点的编程应该使用对话框,如何编辑一个对话框,很多书中都有介绍,编辑的对话框可参考图5的运行界面。

  头文件Get_IP.h如下:

BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam);


  这个程序只使用了一个对话框过程,一般把这个过程的声明放在头文件中。

  源程序Get_IP.c:

#include<winsock2.h>
#include"Get_IP.h"
#include"resource.h" //这个头文件在创建资源的时候会自动生成,
//并会在插入资源时自动生成控件标识号.
int WSA_return;
WSADATA WSAData;

HOSTENT *host_entry;
char host_name[256];
char host_address[256];

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
 WSA_return=WSAStartup(0×0101,&WSAData);
 if(WSA_return==0)
 {
  gethostname(host_name,256);
  host_entry=gethostbyname(host_name);
  if(host_entry!=0)
  {
   wsprintf(host_address,"%d.%d.%d.%d",
    (host_entry->h_addr_list[0][0]&0×00ff),
    (host_entry->h_addr_list[0][1]&0×00ff),
    (host_entry->h_addr_list[0][2]&0×00ff),
    (host_entry->h_addr_list[0][3]&0×00ff));
  }
 }
 WSACleanup();
 DialogBox(hInstance,"DIALOG1",NULL,(DLGPROC)Hostname_ipDlgPro);
 return 0;
}

BOOL APIENTRY Hostname_ipDlgPro(HWND hDlg,UINT message,
WPARAM wParam,LPARAM lParam)
{
 switch(message)
 {
  case WM_INITDIALOG:
   return(TRUE);
  case WM_COMMAND:
   if(LOWORD(wParam)==IDOK)
   {
    SetDlgItemText(hDlg,IDC_EDIT1,host_name);
    SetDlgItemText(hDlg,IDC_EDIT2,host_address);
    SetDlgItemText(hDlg,IDCANCEL,"确定");
   }
   if(LOWORD(wParam)==IDCANCEL)
    EndDialog(hDlg,TRUE);
    return(TRUE);
   break;
 }
 return(FALSE);
}

2003-02-10· · ··动网先锋

  随着互连网应用的深入和发展,三层体系结构的应用模式也得到更多人的青睐。本文介绍了三层结构应用程序的概念和优点,并结合一个实例介绍了如何建立三层结构的ASP应用程序。

  一、两层结构的ASP应用有何缺点

  ASP有一个天生的缺点,就是ASP代码和 HTML代码是混在一起的,ASP程序员既需要考虑与数据库打交道,需要关心如何与HTML配合,有时还需要用ASP直接生成HTML代码。其结果是,当程序逻辑足够复杂时,.asp源文件非常长;而且,无论客户提出用户界面的改变,还是商业逻辑的改变(比如,在考试系统中,"合格"的标准可能从达到60 分就算合格,改为进入前100名才算合格),都需要对.asp文件进行改动,而商业逻辑的改变,很可能需要改动很多文件。

  二、三层结构的概念

  在传统的C/S应用中,也存在着上述同样的问题,多层结构的应用正是在C/S 结构的基础上产生的,并且也扩展到了B/S应用开发领域。 即将应用划分为三层(可以有更多层,但三层最常见): 用户界面层,商业逻辑层,数据库层。

  用户界面层负责处理用户的输入和向用户的输出,但并不负责解释其含义(出于效率的考虑,它可能在向上传输用户输入前进行合法性验证),这一层通常用前端工具(VB,VC,ASP等)开发。

  商业逻辑层是上下两层的纽带,它建立实际的数据库连接,根据用户的请求生成SQL语句检索或更新数据库,并把结果返回给客户端,这一层通常以动态链接库的形式存在并注册到服务器的注册簿(Registry)中,它与客户端通讯的接口符合某一特定的组件标准(如COM,CORBA),可以用任何支持这种标准的工具开发。
 
  数据库层负责实际的数据存储和检索。有了这样的结构,上面的问题迎刃而解:还是以考试系统中的合格标准为例,在客户端所有需要显示合格人员名单的地方,调用这样一个函数 GetQualifiedList,至于这个函数如何编写,如何与数据库打交道,以至访问的是何种数据库都与其无关(你一定有过这样的经历,在一种数据库系统上运行得很好的SQL语句,有时换到另一种数据库系统上必须加以修改); 在中间层DLL中实现这个GetQualifiedList函数,如果用户对"合格"的定义变了,只需要修改这个函数就可以了,只要此函数的入口参数和返回内容不变,在客户端不需作任何改动。在这里,我们看到了面向对象编程的特性之一封装性的优点,而这一点在开发大型应用时尤其有用–我们可以把开发人员分成两组,一组负责开发界面层,另一组负责开发商业逻辑层,双方只要按照事先商定的函数接口,并行地开发就可以,而不必向从前那样,后面的工作必须等前面的工作完成后才能开始。当然,这样的开发模式需要很好的项目协调和文档作支持。

  你也许会问,如果我把这些函数些在一个单独的文件中,再在需要调用的地方把它包含进来,不是同样能达到目的吗? 第一,这种方法效率不高,无论你把这些函数分散到多少个文件中,当你需要调用其中一个时,总会包含进一些实际上并不需要的函数,这无疑加重了服务器的负担,对服务器性能要求较高的Web应用尤其如此。而DLL只在需要时才调入内存且只调入需要的函数,并且多个应用程序实例可以共享同一个DLL实例;第二,设想一个员工,有20个属性(工号,姓名,年龄,性别……),现在给定某工号,要求返回此员工所有信息。此时如果单纯用函数,只能定义20个全局变量,在函数中改变这些变量值,或者定义一个有20个传参(by reference)参数的函数。显然,第一种方法很麻烦而一旦增加一个属性后一种方法就需要更改函数接口。而在一个对象里,既包含成员方法(即函数和过程),也包括成员属性。如果我们采用对象的方法,则在函数中只需要改变对象的属性,在函数外可以直接引用改变了的对象属性值。这种方法有些类似第一种方法,但1.属性值无需在函数外逐一说明;2.这些属性值只属于对象,与对象无关的代码不会无意地改变属性值;3.一旦对象被释放,这些值会被一起释放。

三、如何开发三层结构的ASP应用程序

  ASP具有良好的扩充性,我们访问数据库时,采用的时ADO对象,访问文件时,采用的是文件系统对象(FSO),其实这时程序已经是三层结构的应用程序了,只不过由于是利用内置的对象而为意识到罢了。这些对象都遵循COM/ActiveX接口,因此我们自己开发的对象也要遵循这个接口。下面,我们就以上文提到的"合格"标准为例,演示如何创建自己的三层结构的ASP应用。

  1、在数据库系统中建立如下数据库表:
    Employee: EMPLID char (5) not null,
             Name  char (10) not null,
             Gender char (1) not null,
             Score   int not null

  此表存储员工信息和考试成绩,为简单起见,这里只包含工号,姓名和性别三项,并且只有一门考试,EMPLID为主键。

 

  2、建立动态链接库

  启动VB(这里以VB为例,你可以用你喜欢的任何支持ActiveX接口的开发工具开发),新建一工程,工程类型为ActiveX DLL。在工程中新建一个类,取名为Employee。你可以Class Builder可视化的向类中填加属性和方法,也可以直接手工编辑。首先填加EMPLID属性如下:

  Private msEMPLID as string
  Property Let EMPLID(sEMPLID as string)
   msEMPLID=sEMPLID
  End Property
  Property Get EMPLID() as string
   EMPLID=msEMPLID
  End Property

  一般地讲,每一个属性都应该有Property Let和Property Get两个方法,它们分别当向属性赋值和读取属性值时被调用。如果某个属性只被赋值而从不被读取(这种情况多发生在对应数据库表的主键的属性上),则 Property Get方法可以省略。Property Let方法不能省略。你可以仿照上面的程序再建立Name,Gender和Score三个属性。然后创建如下方法:

  Public Sub Create(EMPLID as string)
  dim conn as new Connection
  dim rs as new Recordset
  dim sql as string
  ’Suppose that you create a DSN in the control panel, the connectionstring property
  ’can also be dsn-less string
  conn.ConnectionString="dsn=dsnname;uid=username;password=pwd"
  conn.open
  sql="select * from Employee where EMPLID=’" & EMPLID & "’"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     msEMPLID=trim(.Fields("EMPLID"))
     msName=trim(.Fields("Name"))
     msGender=trim(.Fields("Gender"))
     msScore=.Fields("Score")
   end if
   .close
  end with
  set rs=nothing
  conn.close
  set conn=nothing
  End Sub

  这里根据EMPLID创建Employee对象,注意数据库中的值是赋给三个私有变量,而不是直接赋值给属性,如果你单步调试就会发现,给msEMPLID赋值会调用Property Let EMPLID,也就是给属性赋值。

  下面我们再创建一个类Employees,并填加如下方法:

  private colQualifiedList as new Collection
  private mnCurrentIndex as integer
  Public Sub GetQualifiedList()
  dim conn as new Connection
  dim rs as new Recordset
  dim sql as string
  ’Suppose that you create a DSN in the control panel, the connectionstring property
  ’can also be dsn-less string
  conn.ConnectionString="dsn=dsnname;uid=username;password=pwd"
  conn.open
  sql="select EMPLID from Employee where Score>=60 order by Score desc"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     do while not .eof
       dim oEmployee as new Employee
       oEmployee.Create trim(.Fields("EMPLID"))
       colQualifiedList.Add oEmployee
       set oEmployee=nothing
     loop
   end if
   .close
  end with
  set rs=nothing
  conn.close
  set conn=nothing
  End Sub

  首先请注意VB中创建类实例的语法dim oEmployee as new Employee,后面会看到,在ASP中创建类实例的语法是不同的。这个方法检索成绩大于等于60的员工工号,并据此创建一个Employee对象,再将此对象加入私有的集合对象中。下面两个函数遍历集合中的元素:

  Public Function GetFirst() as Employee
   if colQualifiedList.count>0 then
    mnCurrentIndex=1
     set GetFirst=colQualifiedList.Item(1)
   else
     set GetFirst=nothing
   end if
  End Function
  Public Function GetNext() as Employee
   mnCurrentIndex=mnCurrentIndex+1
   if mnCurrentIndex>colQualifiedList.count then
     set GetNext=nothing
   else
     set GetNext=colQualifiedList.Item(mnCurrentIndex)
   End if
  End Function

  也许你会说,为何不把集合声明Public,这样在ASP中不是可以直接引用吗?确实,这样也行得通,编程实现起来也更简单些,但是,这样做破坏了封装性原则。因为数据以何格式存储完全是商业逻辑层的事,与用户界面层无关,假设有一天你因为每种原因放弃了用集合来存储数据的设计,而改用数组或记录集 (Recordset)来存储,那你只需要修改GetFirst和GetNext两个函数,用户界面层完全无需修改。
至此类文件创建完毕,将工程文件存为 test.vbp,选File菜单下的Make test.dll选项将其编译。

  3、注册动态链接库

  启动Web Server 上的Microsoft Transaction Server (Start–Windows NT Optionpack4–Internet Information Server–Internet Service Manager),展开Microsoft Transaction Server–Computer–My Computer–Package Installed,点鼠标右键选New–Package–Create Empty Package,输入包名Test(这里Test是任选的名字,不一定要与DLL同名),OK-Interactive User-the current Logon user–Finish。双击Test–Component,右键选Component-New-Component-Install New component(s)– Add File,选择你刚编译好的DLL文件,MTS会发现DLL中有两个类Employee和Employees。至此DLL注册完毕。

  4、编写ASP程序

  <HTML><Body>
  <p>Qualified Employee List</p>
  <table border=1 cellspacing=0 cellpadding=0>
  <tr>
   <td>Employee ID</td>
   <td>Name</td>
   <td>Gender</td>
   <td>Score</td>
  </tr>
  <%
   set oEmployees=server.createobject("Test.Employees")
   oEmployees.GetQualifiedList
   set oEmployee=oEmployees.GetFirst()
   do while not oEmployee is nothing
  %>
  <tr>
   <td><%=oEmployee.EMPLID%></td>
   <td><%=oEmployee.Name%></td>
   <td><%=oEmployee.Gender%></td>
   <td><%=oEmployee.Score%></td>
  </tr>
  <%
     set oEmployee=oEmployees.GetNext()
   loop
  %>
  </table>
  </body></html>

  注意在ASP中创建类实例的语法set oEmployees=server.createobject("Test.Employees"),其中Test是DLL的名字,Employees 是类的名字; 当然,如果一个函数的返回值是一个对象,类似set oEmployee=oEmployees.GetFirst()这样的语法也是可以的。

  至此,一个完整的三层结构的应用程序已经完成了,让我们看以下,如果把"合格"的定义改为:只有成绩进入前100名才算合格,程序需要做那些修改。事实上,如果你的数据库系统是SQL Server,你只需把SQL语句改为: sql="select top 100 EMPLID from Employee order by Score desc" 就已经可以了,即使为了跨数据库系统的兼容性,我们也只需要对GetQualifiedList做如下修改:

  sql="select EMPLID from Employee order by Score desc"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     i=1
     do while (not .eof) and (i<=100)
       dim oEmployee as new Employee
       oEmployee.Create trim(.Fields("EMPLID"))
       colQualifiedList.Add oEmployee
       set oEmployee=nothing
       i=i+1
     loop
   end if
   .close
  end with
  …
  
  然后把DLL重新编译,注册就可以了,ASP程序完全不必修改。

  四、一些说明和注意事项

  1、由于这个例子比较简单,在Employee类中可以没有Create方法,而在Employees类中将员工的所有信息(工号,姓名,性别,成绩)都读出来并将其赋给Employee对象对应的属性。但在实际应用中,当Employee对象的属性增多,或表的数量增多,表之间关系变复杂时,还是本文所示的方法更有效,代码重用的机会更大。

  2、当DLL被修改后,在MTS中只能将其删除后重新注册,因为每次重新编译后在注册表中对象的ID值都将重新生成。

  3、从ASP中调用带参数的类方法和函数时,所有的变量参数一定要用相应的类型转换函数转换后再传入,否则会引起类型不匹配错误,因为VBScript中只有Variant类型,它不能自动转换成其它类型。例如,有如下的函数定义:

  Public Function Fun1(p1 as string,p2 as integer) as integer
  End Function
  在ASP程序中应如下调用:
  <%
   p1=obj.property1 ‘ Property1 is a string property
   p2=obj.property2 ‘Property2 is an integer property
   a=obj.Fun1(cstr(p1),cint(p2))
   a=obj.Fun1("aaa",10) ‘ constant parameter need not be changed
  %>

  而下面的两种写法是错误的:

  <%
   p1=obj.property1 ‘ Property1 is a string property
   p2=obj.property2 ‘Property2 is an integer property
   a=obj.Fun1(p1,p2) ‘ incorrect,p1 and p2 are variant variables
   p1=cstr(p1)
   p2=cint(p2)
   a=obj.Fun1(p1,p2) ‘ still incorrect
  %>

  这里第二种写法仍然是错误的,即使经过了类型转换,p1和p2仍然是Variant变量。在VBScript中,数据类型和类型转换函数只在表达式运算中起作用,变量只有Variant一种类型。

  结束语

  以上对多层结构的理论和实践进行了一番探讨,希望能对您的开发有所帮助。这里还有一个问题,即类和类的成员该如何设计。这既涉及面向对象编程的理论,也需要一定的实践经验。请参考相关的OOP理论书籍并在实践中不断总结,相信您一定能设计出自己的完美的多层结构的应用程序。


 

  2、建立动态链接库

  启动VB(这里以VB为例,你可以用你喜欢的任何支持ActiveX接口的开发工具开发),新建一工程,工程类型为ActiveX DLL。在工程中新建一个类,取名为Employee。你可以Class Builder可视化的向类中填加属性和方法,也可以直接手工编辑。首先填加EMPLID属性如下:

  Private msEMPLID as string
  Property Let EMPLID(sEMPLID as string)
   msEMPLID=sEMPLID
  End Property
  Property Get EMPLID() as string
   EMPLID=msEMPLID
  End Property

  一般地讲,每一个属性都应该有Property Let和Property Get两个方法,它们分别当向属性赋值和读取属性值时被调用。如果某个属性只被赋值而从不被读取(这种情况多发生在对应数据库表的主键的属性上),则 Property Get方法可以省略。Property Let方法不能省略。你可以仿照上面的程序再建立Name,Gender和Score三个属性。然后创建如下方法:

  Public Sub Create(EMPLID as string)
  dim conn as new Connection
  dim rs as new Recordset
  dim sql as string
  ’Suppose that you create a DSN in the control panel, the connectionstring property
  ’can also be dsn-less string
  conn.ConnectionString="dsn=dsnname;uid=username;password=pwd"
  conn.open
  sql="select * from Employee where EMPLID=’" & EMPLID & "’"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     msEMPLID=trim(.Fields("EMPLID"))
     msName=trim(.Fields("Name"))
     msGender=trim(.Fields("Gender"))
     msScore=.Fields("Score")
   end if
   .close
  end with
  set rs=nothing
  conn.close
  set conn=nothing
  End Sub

  这里根据EMPLID创建Employee对象,注意数据库中的值是赋给三个私有变量,而不是直接赋值给属性,如果你单步调试就会发现,给msEMPLID赋值会调用Property Let EMPLID,也就是给属性赋值。

  下面我们再创建一个类Employees,并填加如下方法:

  private colQualifiedList as new Collection
  private mnCurrentIndex as integer
  Public Sub GetQualifiedList()
  dim conn as new Connection
  dim rs as new Recordset
  dim sql as string
  ’Suppose that you create a DSN in the control panel, the connectionstring property
  ’can also be dsn-less string
  conn.ConnectionString="dsn=dsnname;uid=username;password=pwd"
  conn.open
  sql="select EMPLID from Employee where Score>=60 order by Score desc"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     do while not .eof
       dim oEmployee as new Employee
       oEmployee.Create trim(.Fields("EMPLID"))
       colQualifiedList.Add oEmployee
       set oEmployee=nothing
     loop
   end if
   .close
  end with
  set rs=nothing
  conn.close
  set conn=nothing
  End Sub

  首先请注意VB中创建类实例的语法dim oEmployee as new Employee,后面会看到,在ASP中创建类实例的语法是不同的。这个方法检索成绩大于等于60的员工工号,并据此创建一个Employee对象,再将此对象加入私有的集合对象中。下面两个函数遍历集合中的元素:

  Public Function GetFirst() as Employee
   if colQualifiedList.count>0 then
    mnCurrentIndex=1
     set GetFirst=colQualifiedList.Item(1)
   else
     set GetFirst=nothing
   end if
  End Function
  Public Function GetNext() as Employee
   mnCurrentIndex=mnCurrentIndex+1
   if mnCurrentIndex>colQualifiedList.count then
     set GetNext=nothing
   else
     set GetNext=colQualifiedList.Item(mnCurrentIndex)
   End if
  End Function

  也许你会说,为何不把集合声明Public,这样在ASP中不是可以直接引用吗?确实,这样也行得通,编程实现起来也更简单些,但是,这样做破坏了封装性原则。因为数据以何格式存储完全是商业逻辑层的事,与用户界面层无关,假设有一天你因为每种原因放弃了用集合来存储数据的设计,而改用数组或记录集 (Recordset)来存储,那你只需要修改GetFirst和GetNext两个函数,用户界面层完全无需修改。
至此类文件创建完毕,将工程文件存为 test.vbp,选File菜单下的Make test.dll选项将其编译。

  3、注册动态链接库

  启动Web Server 上的Microsoft Transaction Server (Start–Windows NT Optionpack4–Internet Information Server–Internet Service Manager),展开Microsoft Transaction Server–Computer–My Computer–Package Installed,点鼠标右键选New–Package–Create Empty Package,输入包名Test(这里Test是任选的名字,不一定要与DLL同名),OK-Interactive User-the current Logon user–Finish。双击Test–Component,右键选Component-New-Component-Install New component(s)– Add File,选择你刚编译好的DLL文件,MTS会发现DLL中有两个类Employee和Employees。至此DLL注册完毕。

  4、编写ASP程序

  <HTML><Body>
  <p>Qualified Employee List</p>
  <table border=1 cellspacing=0 cellpadding=0>
  <tr>
   <td>Employee ID</td>
   <td>Name</td>
   <td>Gender</td>
   <td>Score</td>
  </tr>
  <%
   set oEmployees=server.createobject("Test.Employees")
   oEmployees.GetQualifiedList
   set oEmployee=oEmployees.GetFirst()
   do while not oEmployee is nothing
  %>
  <tr>
   <td><%=oEmployee.EMPLID%></td>
   <td><%=oEmployee.Name%></td>
   <td><%=oEmployee.Gender%></td>
   <td><%=oEmployee.Score%></td>
  </tr>
  <%
     set oEmployee=oEmployees.GetNext()
   loop
  %>
  </table>
  </body></html>

  注意在ASP中创建类实例的语法set oEmployees=server.createobject("Test.Employees"),其中Test是DLL的名字,Employees 是类的名字; 当然,如果一个函数的返回值是一个对象,类似set oEmployee=oEmployees.GetFirst()这样的语法也是可以的。

  至此,一个完整的三层结构的应用程序已经完成了,让我们看以下,如果把"合格"的定义改为:只有成绩进入前100名才算合格,程序需要做那些修改。事实上,如果你的数据库系统是SQL Server,你只需把SQL语句改为: sql="select top 100 EMPLID from Employee order by Score desc" 就已经可以了,即使为了跨数据库系统的兼容性,我们也只需要对GetQualifiedList做如下修改:

  sql="select EMPLID from Employee order by Score desc"
  with rs
   .open sql,conn,1,3
   if .eof and .bof then
     exit sub
   else
     i=1
     do while (not .eof) and (i<=100)
       dim oEmployee as new Employee
       oEmployee.Create trim(.Fields("EMPLID"))
       colQualifiedList.Add oEmployee
       set oEmployee=nothing
       i=i+1
     loop
   end if
   .close
  end with
  …
  
  然后把DLL重新编译,注册就可以了,ASP程序完全不必修改。

  四、一些说明和注意事项

  1、由于这个例子比较简单,在Employee类中可以没有Create方法,而在Employees类中将员工的所有信息(工号,姓名,性别,成绩)都读出来并将其赋给Employee对象对应的属性。但在实际应用中,当Employee对象的属性增多,或表的数量增多,表之间关系变复杂时,还是本文所示的方法更有效,代码重用的机会更大。

  2、当DLL被修改后,在MTS中只能将其删除后重新注册,因为每次重新编译后在注册表中对象的ID值都将重新生成。

  3、从ASP中调用带参数的类方法和函数时,所有的变量参数一定要用相应的类型转换函数转换后再传入,否则会引起类型不匹配错误,因为VBScript中只有Variant类型,它不能自动转换成其它类型。例如,有如下的函数定义:

  Public Function Fun1(p1 as string,p2 as integer) as integer
  End Function
  在ASP程序中应如下调用:
  <%
   p1=obj.property1 ‘ Property1 is a string property
   p2=obj.property2 ‘Property2 is an integer property
   a=obj.Fun1(cstr(p1),cint(p2))
   a=obj.Fun1("aaa",10) ‘ constant parameter need not be changed
  %>

  而下面的两种写法是错误的:

  <%
   p1=obj.property1 ‘ Property1 is a string property
   p2=obj.property2 ‘Property2 is an integer property
   a=obj.Fun1(p1,p2) ‘ incorrect,p1 and p2 are variant variables
   p1=cstr(p1)
   p2=cint(p2)
   a=obj.Fun1(p1,p2) ‘ still incorrect
  %>

  这里第二种写法仍然是错误的,即使经过了类型转换,p1和p2仍然是Variant变量。在VBScript中,数据类型和类型转换函数只在表达式运算中起作用,变量只有Variant一种类型。

  结束语

  以上对多层结构的理论和实践进行了一番探讨,希望能对您的开发有所帮助。这里还有一个问题,即类和类的成员该如何设计。这既涉及面向对象编程的理论,也需要一定的实践经验。请参考相关的OOP理论书籍并在实践中不断总结,相信您一定能设计出自己的完美的多层结构的应用程序。

2005年08月21日

一、数据库远程管理技术

  基于互联网的广域网现代应用中的一个重要环节是数据库远程监控。首先简单回顾一下互联网上的数据库远程管理技术的发展过程和方式:

  早期通过编写CGI-BIN程序模块进行数据库远程管理。但CGI-BIN的运行速度慢,维护很不方便,现在已经基本被弃用。

  这几年使用组件对象模型(Component Object Model, COM)的应用非常多,效果也很好。但如果使用的是第三方服务器(笔者的网站就是建立在第三方的虚拟主机上),服务器方往往因为保密或其它商业原因不允许用户注册自己的组件。

  近年来由微软公司推出的.NET平台和SUN公司的J2EE平台都是非常高档的数据库远程管理与服务平台。都能提供优质的多层(n-Tier)应用服务。

  其中,.NET的简单对象访问协议(Simple Object Access Protocol, SOAP)使用超文本传输协议(Hypertext Transfer Protocol, HTTP)和扩展标记语言(Extensible Markup Language, XML)技术实现跨系统(例如Windows – Linux)的通讯服务方式已经广为开发商接受和使用。许多大型应用,例如企业资源计划(Enterprise resource planning, ERP)等都建立在这样的大型平台之上。但对于中小型应用,比如一个网站的建设和维护,这种大型应用平台就显得有些尾大不掉,开销也过于庞大。

  曾经在互联网技术和Java技术方面一度落后的微软公司在XML应用开发则走在了前头。她的XML解析器(MSXML)中的XMLHTTP协议是一个非常方便实用的客户/服务通讯管道。综合运用XMLHTTP以及ActiveX数据对象(ActiveX Data Objects, ADO/ADOX)可以简单方便地实现数据库远程管理。

  本文介绍如何综合运用XMLHTTPADO/ADOX进行远程数据库管理。

二、数据库远程管理体系

数据库远程管理的任务流程是:

1、客户端向服务端发出数据库结构和数据的查询或修改指令。
2
、服务端接受并执行有关指令并向客户端返回结果。
3
、客户端接受并显示服务端返回的指令执行结果。

实现数据库远程管理的二个主要关键环节是:

1、客户端与服务端之间的指令上传和结果下传的数据通道,由XMLHTTP协议实现。
2
、服务端前沿与数据库之间的指令传送和结果返回,由起着中间层作用的ADO/ADOX接口完成。

三、XMLHTTP的使用

  顾名思义,XMLHTTP是个传送XML格式数据的超文本传输协议。

  实际上,XMLHTTP的数据传输过程更为灵活一些:

1.       它上传的指令可以是XML格式数据,也可以是字符串,流,或者一个无符号整数数组。还可以是URL的参数。

2.       它下达的结果可以是XML格式数据,也可以是字符串,流,或者一个无符号整数数组。

客户端调用XMLHTTP的过程很简单,只有5个步骤:

1、创建XMLHTTP对象
2
、打开与服务端的连接,同时定义指令发送方式,服务网页(URL)和请求权限等。
   
客户端通过Open命令打开与服务端的服务网页的连接。与普通HTTP指令传送一样,可以用"GET"方法或"POST"方法指向服务端的服务网页。
3
、发送指令。
4
、等待并接收服务端返回的处理结果。
5
、释放XMLHTTP对象

XMLHTTP方法:
Open bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword
    bstrMethod
:数据传送方式,即GETPOST
    bstrUrl
:服务网页的URL
    varAsync
:是否同步执行。缺省为True,即同步执行,但只能在DOM中实施同步执行。 应用中一般将其置为False,即异步执行。
    bstrUser
:用户名,可省略。
    bstrPassword
:用户口令,可省略。

Send varBody
    varBody
:指令集。可以是XML格式数据,也可以是字符串,流,或者一个无符号整数数组。也可以省略,让指令通过Open方法的URL参数代入。
    
setRequestHeader bstrHeader, bstrValue
    bstrHeader
HTTP (header)
    bstrValue
HTTP (header)的值
   
如果Open方法定义为POST,可以定义表单方式上传: 
   
xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" 
    
XMLHTTP
属性:
onreadystatechange
:在同步执行方式下获得返回结果的事件句柄。只能在DOM中调用。
responseBody
:结果返回为无符号整数数组。
responseStream
:结果返回为IStream流。
responseText
:结果返回为字符串。
responseXML
:结果返回为XML格式数据。
    

下面是本文附件源程序中的一个应用示例:

Function GetResult(urlStr)
Dim xmlHttp
Dim retStr
 
Set xmlHttp = CreateObject("Msxml2.XMLHTTP")    ‘创建对象

On Error Resume Next      ‘出错处理

xmlHttp.Open "POST", urlStr, False     ‘用POST方式打开连接,异步执行。

xmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"       ‘上传表单

xmlHttp.Send      ‘发送指令

If Err.Number = 0 Then        ‘如果连接正确
retStr = xmlHttp.responseText        ‘等待并获得服务端返回的结果字符串

Else
retStr = "Url not found"    ‘否则返回出错信息

End If

Set xmlHttp = nothing       ‘释放对象

GetResult = retStr       ‘返回结果

End Function

GetResult()函数带入一个服务网页的URL参数,把上传的指令安放在URL后面的参数上,如:
   
urlStr = "server.asp?cmd=" & cmd & "&db=" & db & "table=" & table
    cmd
:执行方式,例如查询,修改,删除等等。
    db
:服务端数据库名
    table
:服务端表名
    
然后提交指令,等待并接收返回的处理结果。结果以字符串方式返回。最后由函数调用者处理并显示结果。

 

2005年08月14日

呵呵 这个blog申请好久嘞都没有用.
想下决心渐渐把以前的blog都转移过来…

恩 很喜欢这里这种风格跟功能.
就是少了定时发表这个功能.要是有它就完美啦 哈哈