在我的一个j2ee项目中,当一个人的某一任务到来时,我们在一个jsp页面显示这个到来的任务,提示用户需要处理该任务。
我们是通过轮询数据库来实现对任务的实时监控的。表user_message存储用户的任务。表结构如下:
create table user_message
(
message_id number(9) not null,
task_id varchar2(100),
user_code varchar2(10),
task_name varchar2(50),
is_read varchar2(1),
create_time date,
task_state varchar2(10),
create_man varchar2(10),
send_man varchar2(10),
pre_task_name varchar2(50),
serial_code number(11),
message_title varchar2(200)
)
当is_read=‘f’时,则是新任务。
这个方案有以下弊病:
1:必须打开页面才可以看到任务;
2:每个客户端都需要轮询,当用户多时数据库负荷过大;
于是我做了一个辅助的消息提示工具,当任务到来时发出提示,在系统托盘区发出提示信息,类似qq。
方案如下:
利用套接字(socket)技术,编写客户端、服务端程序。服务端作为消息服务器,采用每隔一段时间轮询数据库的方式实时监控user_message表。
把新任务消息发送到客户端;客户端识别该消息是否是“我的”消息,如果是“我的消息”,则在系统托盘区闪烁,用户点击闪烁图标,则可以看到消息标题,点击消息标题下
的箭头图案,则可以打开页面进入j2ee系统。
好了,现在就来一步一步的用c++builder做这个小东东吧:
需要准备的知识如下:
一:采用自己的消息通讯协议
二:socket编程
三:如何实现系统托盘
四:数据库中的一条记录,如何打包发送到客户端?
我们一点一点的逐一解决:
一:消息通讯协议如下
msg.h
/*
* create date: 2004-12-01
* create by: 李春雷
* purpose: 协议用自定义消息结构:
* messageinfo:任务消息
* msgtype消息头:0xa登陆成功,0xb登陆失败,0xc工作消息,0xd任务结束标识
* logininfo:登陆消息
*/
//------------------------------------------------------------------------------
struct messageinfo{ //消息结构
int msgtype; //消息头:0xa登陆成功,0xb登陆失败,0xc工作消息,0xd任务结束标识
char messageid[10]; //任务序号
char usrcode[10]; //用户帐号
//char tastname[50]; //任务名称
char tastname[200]; //任务名称
char creattime[20]; //时间
};
struct logininfo{ //登陆信息
char pwd[20]; //用户密码
char userid[30]; //用户id
};
//------------------------------------------------------------------------------
服务端发送的消息只采用的是一个结构体messageinfo(确认是否登陆成功和发出任务消息),客户端只发送一次登陆信息(logininfo)
给服务端,其他时间只是接受服务端发来的消息。
二:socket编程
如果没有用过socket编程,没关系,现在赶快学习:
c++ builder提供了internet套件,其中的tclientsocket和tserversocket组件封装了windows的有关api,大大简化了winsock编程。
要通过internet传输数据,至少需要一对socket,一个socket在客户端,另一个socket在服务器端。其实tclientsocket、tserversocket组件并不是socket对象,
其属性socket将返回各自的socket对象。tclientsocket用来处理客户端到服务器端之间的socket连接,tserversocket用来处理由客户端发来的socket连接,
一旦客户端和服务器端都接通了socket,客户端和服务器端就可以相互通信了。
我们做一个小例子:
---- 建立一新项目,创建应用程序的用户界面:
---- 1.将组件页切换到internet页,放一个tserversocket组件和一个tclientsocket组件到窗体上,这样应用程序既可以是tcp/ip服务器,也可以是tcp/ip客户。
将port属性都设为同一个值(如1000),确定socket之间的连接类型为nonblocking(非阻塞方式)。
---- 2.放两个tmemo组件到窗体上,用来分别显示双方的谈话内容,将memo2的readonly属性设为true。
---- 3.在窗体的顶部放上一个panel组件,在其上放三个按钮:监听(btnlisten)、连接(btnconnect)、断开(btndisconnect),用来启动相应的操作。
---- 4.在窗体底部放一个statusbar组件,将其simplepanel属性设为true,在相应的事件处理程序中改变状态条信息,让用户随时了解连接状态。
---- 打开头文件,在窗体类的private段添加两个私有成员: bool isserver;string server。双方通信时需同时运行chat程序,isserver用来确定哪个
chat程序处于服务器端,server用来存放服务器的主机名。建立窗体类的构造器如下:
__fastcall tform1::tform1(tcomponent* owner)
: tform(owner)
{
isserver=false;
server="localhost";
}
---- 这里server被缺省设为localhost,这样程序可以在没有连入internet的单机上进行调试。在windows子目录下你可以找到hosts.sam文件中,在该文件
中已经将本机ip地址127.0.0.1定义了主机名:localhost。