摘 要: 利用ActiveX控件技术,结合B/S模式与C/S模式的双重优点,将C/S模式中的socket网络通信技术移植于B/S模式中,实现单态模式登录,为基于B/S模式应用系统的客户端与服务器的通信提供了一种新的解决方案。
关键词: 单态; B/S模式; C/S模式; ActiveX组件
单态(Singleton)模式的主要作用是使得一个类Class只有一个实例存在,即该模式仅允许有且仅有一个实例在运行。在很多C/S模式的软件中经常会遇到单态模式的应用。用户用一个账号登录系统之后,如果想再用第二个账号登录,必须先把第一个账号注销。该模式在C/S模式中实现比较简单,但在B/S模式中实现却比较复杂。在B/S模式中,浏览器本身并不是单态模式,用户可以打开多个浏览器来登录同一个系统,例如在浏览器的实例1中用“张三”登录,再打开浏览器的实例2,用“李四”登录,这时虽然是用两个浏览器实例在系统中登录了两个账号,但这两个实例之间会相互影响,特别是与服务器通信时,容易带来通信对象错误的问题。
B/S模式程序中一般会采用Session或cookie来保存登录信息,便于在其他的页面中使用,以避免多次重复登录系统,即所谓的单点登录(SSO)模式。在前面所举的例子中,用“张三”登录后,可将其保存在session中,令Session[‘username’]=“张三”;如果再用“李四”登录,同样也可保存在Session中,Session[‘username’]=“李四”;由于系统中的Session是唯一的,所以这时Session[‘username’]会覆盖前面的值,使得在用“张三”登录的系统中实际保存的登录信息变成了“李四”。
1 单态登录模式功能
本文所提到的单态登录模式拟实现以下功能:
(1) 在一台机器上只能登录一个账号,如果已经登录了一个账号,再次登录时则提示登录失败。
(2) 一个账号最多只能在一台机器上登录,如果要登录的账号已在其他的机器上登录了,则提示登录失败。
实现此项功能的好处之一是在客户端与服务器进行通信时,在查找通信对象时不至于发生错误。
单态模式登录在C/S模式中可以采用很多方法来实现上述功能,但在B/S模式中实现起来却比较困难。最简单的方法是在数据库中建一个数据表Login(字段为UserName和LoginIP),用来保存已登录的登录账号和登录机器的IP信息。每次登录时,先查一下该数据表,确定要登录的账号在Login表中是否已存在,如果不存在则表明该账号尚未登录,允许登录;如果存在则表明已被登录,不可再登录。退出系统时,先将Login表中对应的记录删除掉。
该方法存在的最大问题是:当登录系统后,若出现非正常退出系统的情况(如突然断电、程序崩溃等),则无法将Login表中的记录清除。使得下次登录查询Login表时,误以为该账号仍在登录中,导致登录失败。
有人提出每隔一定时间(如30 s)查询Session来判断用户是否在线,这种方法一方面不能保证百分之百地解决问题,另一方面会给服务器带来不小的负担。本文所给出的B/S模式的单态模式登录方法是利用ActiveX技术结合C/S模式与B/S模式的特点,在ActiveX控件中运用网络通信技术来解决前面所提到的问题。
2 关键技术
ActiveX是微软提出的采用COM(Component Object Model)和DCOM(Distributed Component Object Model)使软件组件在网络环境中进行交互的一组技术集,它是在COM之上建立的一种理论和概念,与具体的编程语言无关,包括ActiveX Dll组件和ActiveX控件。
本文采用的方法是ActiveX控件。在ActiveX控件中,运用socket网络通信技术实现客户端与服务器之间的通信,或者客户端与客户端之间的直接通信。用户可在不安装客户端程序的情况下直接通过浏览器与服务器或其他客户端进行通信。Activex控件可直接嵌入Web页面,在Web页面中通过<object>标签来创建,
<object>标签包含控件的类ID(CLSID),用于识别需要实例化的ActiveX控件,<object>标签中也可指定控件的CodeBase属性值,供用户查找和自动下载该控件并在本地注册,访问和控制远程服务器的数据:如下面代码所示:
<object id= "SendCtr" width=0 height=0
classid="clsid:6571016D-39C4-47AB-9425-9995F68AABE4" codebase="SendMsg.CAB"></object>。
控件技术的具体实现过程为:当浏览器发出请求时,Web服务器向用户浏览器回传内嵌ActiveX控件的页面,由浏览器负责解释。在解释过程中首先用该控件在页面中注明的ID值,在本地的注册表内进行查询,若已经存在,则说明该控件已经在本地安装,然后通过注册表中的相关信息直接使用该控件;否则就要根据页面中所提示的该控件所在的服务器上的路径到服务器上下载并且自动完成在本地的安装注册,使该控件成为本地资源,供以后使用。当Web服务器提供更高版本的ActiveX控件时,浏览器会自动下载新的控件,并自动安装,覆盖原来的控件。控件提供了接口方法,可以在页面中用JavaScript脚本语言来调用,如:
document.getElementById("SendCtr").Send(“192.168.
0.13”,”Hello!”);
此处调用的是SendCtr控件的Send方法,用于向IP为“192.168.0.13”发送消息”Hello!”。
3 实现原理
要实现网络通信的功能,可在页面中加入两个activex控件:SendMsg和RecvMsg,一个用于发送消息,另一个用于接收消息。SendMsg控件放在登录页面中,RecvMsg控件放在登录后的用户操作界面中,每次登录时,如果发现要登录的账号在Login表中已经存在,则先由SendMsg控件检测目的账号是否在线,如果检测出不在线,说明该账号是上次登录后非正常退出了,使得Login表没有及时删除该条记录,所以先将该记录删除掉,再将本次登录的记录插入Login 表中;如果检测到对方在线,则提示该账号已被人登录了,本次登录失败,可由逻辑流程图(如图1)实现上面提到的两个功能(设登录账号为zhangsan,本机IP为192.168.0.13)。
4 核心代码
在SendMsg控件中,提供了一个接口函数:CheckIsOnLine(LPCTSTR strDestIP)。该接口函数仅有一个参数strDestIP,即要检测是否在线的目的IP。该函数用来检测目的IP上的系统是否在线,实现的原理也较简单:给该IP发送一个消息,如果在规定时间内收到回复,则说明对方在线,因为只有其在线,才能在登录后的用户界面中用RecvMsg控件回复消息。CheckIsOnLine内部实现主要源码如下:
CheckIsOnLine(LPCTSTR strDestIP)
{
char msg[10];
strcpy_s(msg,".");
sockaddr_in checkaddr;
checkaddr.sin_family = AF_INET;
checkaddr.sin_addr.S_un.S_addr = inet_addr(strDestIP);
checkaddr.sin_port = htons(5002);
//连接目的客户端,向目的客户端发送信息".",看有无回复
sendto(m_Socket,msg,10,0,(sockaddr*)&checkaddr,sizeof
(checkaddr));
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(skt,&rfd);
timeval time;
time.tv_sec = 0;
time.tv_usec = 500;
int iResult = select(0,&rfd,NULL,NULL,&time);
//检测在500 ms内有无回信
if(!iResult) //对方没有回信
{CString strSql = "delete Login where LoginIP =′"+ strDestIP +"′";
m_Ado.CmdExcute(strSql,FALSE);
//将Login表中数据删除
}
else
{ char* pData = new char[1024];
memset(pData,0,1024);
sockaddr_in addr;
int factsize = sizeof(sockaddr);
int ret =recvfrom(m_Socket,pData,1024,0,(sockaddr*)&addr,&factsize);
if (ret > 0) //对方在线,提示登录失败
{
MessageBox("该用户已登录且尚未退出系统,登录失败!","提示");
}
}
}
在RecvMsg控件中只需在接受消息时,判断消息如果为".",回复一个消息即可。
本文所给出的方法已在Windows XP系统、ASP.net3.5、IE7.0环境下测试通过。利用该方法也可以实现WebQQ的即时通信功能。利用Activex组件技术,可以很好地发挥B/S模式与C/S模式的双重优点,采用混合工作模式及合理的功能配制,克服单一的B/S模式或单一C/S模式安全与效率、功能与应用的多种矛盾与不足,为开发一个完善的应用系统提供借鉴。将ActiveX技术应用于B/S监控软件中,不仅增强了B/S监控软件的功能,加快了软件的开发速度,而且适应了当前软件开发向模块化、开放化发展的趋势,提高了系统的实时性、可靠性和可扩展性。ActiveX技术应用于B/S模式弥补了单B/S模式的不足,比B/S和C/S结合的方式简单实用(不需要安装C/S客户端),可以用在商业化的在线杀毒、在线点播、在线考试等诸多领域,具有较大的应用参考价值。
参考文献
[1] 郑健,庖丁解牛.纵向切入ASP.NET 3.5控件和组件开发技术(第一版)[M].北京:电子工业出版社,2009.
[2] (美)伊夫杰等. ASP.NET 3.5高级编程(第5版)[M].北京:清华大学出版社,2008.
[3] (美)杰瑞夫(Jeffrey, J.)等. Windows核心编程(第5版)[M].北京:清华大学出版社,2008.
[4] (美) 维埃拉,董明.SQL Server 2005高级程序设计(第一版)[M].北京:人民邮电出版社,2008.