本文我们打算使用DCOM来开发个局域网聊天室不仅是作为技术上研究实际上我相信这应该也是个有用工具首先我们要对这个聊天室功能有个大致了解:
1、至少这个聊天室应该允许多个局域网用户进行聊天
2、应该能够有多个话题子聊天室用户可以选择进入某个聊天室进行聊天
3、客户端应该尽量简单(不用配置DCOM)并需要个服务器端管理所有交互行为管理聊天室数目和相关配置并做好系统监测和日志记录等
4、对聊天室功能进行扩展(如悄悄话功能表情符号等)根据以上功能描述在仔细分析问题以后我们设计出下面草图:
这篇文章中我们要大致实现这个个基本核心包括IChatManager、TChatRoomManager、TchatRoom完成个最基本功能服务器端并做个简单客户端进行检测我们重点是服务器端它将实现聊天室大部分功能客户端只是个十分小巧简单
由于篇幅关系我们只列出重要部分代码完整请给我发email首先来看看我们IchatManager接口是什么样子:
IChatManager = erface(IDispatch)
['{E7CD7F0D-447F-497A-8C7B-1D80E748B67F}']
procedure SpeakTo(const content: WideString; destid: Integer); safecall;
//客户向指定房间说话destid为房间号
function ReadFrom(sourceid: Integer): IStrings; safecall;
//客户从指定房间读取谈话内容sourceid为房间号
function ReadReady(id: Integer): Byte; safecall;
//客户检测指定房间是否已经可以读取谈话内容
procedure ConnectRoom(const UserName: WideString; RoomID: Integer); safecall;
//客户登陆指定房间
procedure DisconnectRoom(const UserName: WideString; RoomID: Integer); safecall;
//客户退出指定房间
function TestClearBufferTag(RoomID: Integer): Integer; safecall;
//客户测试指定房间缓冲区清空和否状况
end;
再来看看接口实现类TChatManager部分:
type
TChatManager = (TAutoObject, IChatManager)
protected
function ReadFrom(sourceid: Integer): IStrings; safecall;
//在这里我们使用Delphi扩展复杂类型TStings为了让COM支持这种
//类型delphi提供了IStrings接口
procedure SpeakTo(const content: WideString; destid: Integer); safecall;
function ReadReady(id: Integer): Byte; safecall;
//用来提供给客户端查询指定房间是否可读既指定房间缓冲区是否为空
procedure ConnectRoom(const UserName: WideString; RoomID: Integer);
safecall;
procedure DisconnectRoom(const UserName: WideString; RoomID: Integer);
safecall;
function TestClearBufferTag(RoomID: Integer): Integer; safecall;
end;
实现部分:
function TChatManager.ReadFrom(sourceid: Integer): IStrings;
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(sourceid);
while TempRoom.Locked do
begin
//do nothing只是等待解锁
end;
GetOleStrings(TempRoom.OneRead,Result);
end;
procedure TChatManager.SpeakTo(const content: WideString; destid: Integer);
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(destid);
while TempRoom.Locked do
begin
//do nothing只是等待解锁
end;
TempRoom.OneSpeak(content);
end;
function TChatManager.ReadReady(id: Integer): Byte;
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(id);
TempRoom.CanRead then result:=1 Result:=0;
end;
procedure TChatManager.ConnectRoom(const UserName: WideString;
RoomID: Integer);
//客户端通过接口登陆到指定房间没有完全实现
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(RoomID);
TempRoom.LoginRoom(UserName);
end;
procedure TChatManager.DisconnectRoom(const UserName: WideString;
RoomID: Integer);
//客户端通过接口离开指定房间没有完全实现
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(RoomID);
TempRoom.LeaveRoom(UserName);
end;
function TChatManager.TestClearBufferTag(RoomID: Integer): Integer;
var
TempRoom:TChatRoom;
begin
TempRoom:=ChatRoomManager.FindRoomByID(RoomID);
result:=TempRoom.ClearBufferTag;
end;
initialization
TAutoObjectFactory.Create(ComServer, TChatManager, Class_ChatManager,
ciMultiInstance, tmApartment);
end.
比较关键TchatRoom是下面样子:
type
TChatRoom=
private
FBuffer:.gif' />[1..20] of ;
FBufferLength:eger;
FRoomName:;
FRoomID:eger;
FLocked:boolean;//同步锁用来处理多人同时发出对话情况
FConnectCount:eger;//当前房间人数
FClearBufferTag:eger;
//每清空次buffer此值便跳变次此脉冲被客户端检测
protected
procedure ClearBuffer;//清空缓冲区
function GetCanRead:boolean;
public
constructor Create(RoomName:;RoomID:eger);
procedure _disibledevent=TempStrings.Count;
end;
end;
个基于DCOM局域网聊天室核心部分就基本完成了并且所有测试都比较顺利这里需要补充介绍说明下聊天室服务器个难点:就是需要开发者非常谨慎处理同步虽然我也进行了定同步处理但在客户端人数众多情况下仍然可能发生死锁或其它活锁情况这个还需要更进步测试、甚至进行定重构
最新评论