分散型COM(以下、DCOMと呼ばれる)の出現により、分散アプリケーションを簡単に作成することができます。アプリケーション、開発者はMS-RPCをほとんど無視できます)、強力な機能と低カップリングを開発することができます(機能的モジュールは比較的独立しています。 OOのアイデアをうまく利用しており、分散コンピューティングシステムを簡単に展開できます。
この記事では、DCOMを使用して、技術研究としてだけでなく、LANチャットルームを開発するつもりですが、実際にこれも便利なツールであるべきだと思います。まず第一に、このチャットルームの機能を一般的に理解する必要があります。
1.少なくともこのチャットルームは、複数のLANユーザーがチャットできるようにする必要があります。
2。複数のトピックを備えたサブチャットルームがある必要があり、ユーザーはチャットルームに参加することを選択できます。
3.クライアントはできるだけ単純である必要があり(DCOMを構成せずに)、サーバー側はすべてのインタラクション動作を管理し、チャットルームと関連する構成の数を管理し、システムの監視とロギングで良い仕事をする必要があります。
4.チャットルームの機能(静かな会話関数、絵文字など)を拡張します。上記の機能の説明に基づいて、問題を慎重に分析した後、次のスケッチを設計しました。
この記事では、iChatmanager、TchatroomManager、Tchatroomなどのこのプログラムの基本的なコアを大まかに実装して、最も基本的な機能を備えたサーバーを完成させ、簡単なクライアント検出を実行したいと考えています。私たちの焦点は、チャットルームのほとんどの機能を実装するため、サーバー側に焦点を当てており、クライアントは非常に小さくシンプルなプログラムです。
スペースのため、重要な部分のコードのみをリストしてください。まず、Ichatmanagerインターフェイスがどのように見えるかを見てみましょう。
iChatmanager = interface(idispatch)
['{e7CD7F0D-447F-497A-8C7B-1D80E748B67F}']
手順(const content:widestring; destid:integer);
//クライアントは指定された部屋に話しかけ、Destidは部屋番号です
function readfrom(sourceid:integer):safecall;
//クライアントは指定された部屋から会話のコンテンツを読み取り、SourceIDは部屋番号です
Function Readeady(ID:Integer):byte;
//顧客は、指定された部屋がすでに会話のコンテンツを読み取ることができるかどうかを確認できます
手順Connectroom(const username:widestring; roomid:integer);
//顧客は指定された部屋にログインします
手順disconnectroom(const username:widestring; roomid:integer);
//顧客は指定された部屋を終了します
function testclearbuffertag(roomid:integer):整数;
//指定された部屋のバッファゾーンがクリアされているかどうかを顧客にテストします
終わり;
インターフェイス実装クラスのTchatManagerセクションをご覧ください。
タイプ
tchatmanager = class(tautoobject、ichatmanager)
保護されています
function readfrom(sourceid:integer):safecall;
//ここでは、これをサポートするために、Delphiによって拡張された複雑なタイプのtstingを使用します
//タイプ、DelphiはISTRINGSインターフェイスを提供します
手順(const content:widestring; destid:integer);
Function Readeady(ID:Integer):byte;
//クライアントに指定されたルームが読み取られているかどうか、指定されたルームバッファが空であるかどうかを照会するために使用されます
手順Connectroom(const username:widestring; roomid:integer);
safecall;
手順disconnectroom(const username:widestring; roomid:integer);
safecall;
function testclearbuffertag(roomid:integer):整数;
終わり;
実装部分:
var
Temproom:tchatroom;
始める
Temproom:= chatroommanager.findroombyid(sourceId);
temproom.locked do
始める
//ロックを解除するのを待っているだけではありません
終わり;
getolestrings(temproom.oneread、result);
終わり;
手順tchatmanager.speakto(const content:widestring; destid:integer);
var
Temproom:tchatroom;
始める
Temproom:= ChatroomManager.findroombyid(destid);
temproom.locked do
始める
//ロックを解除するのを待っているだけではありません
終わり;
temproom.onespeak(content);
終わり;
function tchatmanager.readready(id:integer):byte;
var
Temproom:tchatroom;
始める
Temproom:= Chatroommanager.findroombyid(id);
temproom.canreadの場合、結果:= 1 else results:= 0;
終わり;
手順tchatmanager.connectroom(const username:widestring;
roomid:integer);
//クライアントはインターフェイスを介して指定された部屋にログインし、完全に実装されていません
var
Temproom:tchatroom;
始める
Temproom:= ChatroomManager.findroombyid(roomid);
temproom.loginroom(username);
終わり;
手順tchatmanager.disconnectroom(const username:widestring;
roomid:integer);
//クライアントは指定された部屋をインターフェイスから離れ、完全に実装されていません
var
Temproom:tchatroom;
始める
Temproom:= ChatroomManager.findroombyid(roomid);
temproom.leaveroom(username);
終わり;
function tchatmanager.testclearbuffertag(roomid:integer):integer;
var
Temproom:tchatroom;
始める
Temproom:= ChatroomManager.findroombyid(roomid);
結果:= temproom.clearbuffertag;
終わり;
初期化
tautoObjectFactory.create(comserver、tchatmanager、class_chatmanager、
cimultiinstance、tmapartment);
終わり。
最も重要なtchatroomは次のように見えます:
タイプ
tchatroom = class
プライベート
fbuffer:文字列の配列[1..20]。
fbufferlength:整数;
froomname:string;
Froomid:整数;
群れ:boolean; //同期ロック、複数の人が同時に会話を送る状況を処理するために使用される
fconnectCount:整数; //部屋の現在の人の数
fclearbuffertag:整数;
//この値は、バッファがクリアされるたびに1回ジャンプし、このパルスはクライアントによって検出されます
保護されています
手順ClearBuffer; //バッファをクリアします
関数getCanread:boolean;
公共
Constructor create(roomname:string; roomid:integer);
手順onepeak(content:string); //バッファにチャットコンテンツを追加します
手順Loginroom(username:string); //コメントの実装部分を参照してください
手順Leaveroom(username:string); //コメントの実装部分を参照してください
function oneread:tstrings; //バッファからレコードを読み取ります
プロパティロック:boolean readed; // ichatmanager検出の場合
Property CanRead:Boolean Read getCanread; //バッファが空であるかどうかを判断します。
プロパティClearBuffertag:整数read fclearbuffertag;
終わり;
Tchatroomの実装:
{tchatroom}
constructor tchatroom.create(roomname:string; roomid:integer);
始める
fbufferlength:= 0;
fconnectCount:= 0;
fclearbuffertag:= 1;
群れ:= false;
froomname:= roomname;
Froomid:= roomid;
終わり;
手順tchatroom.clearbuffer;
var
I:整数;
始める
///ここでは、フラグを検出して、サーバーが各チャットコンテンツを記録する必要があるかどうかを判断できます。
i:= 1から20の場合
fbuffer [i]:= '';
fbufferlength:= 0;
fclearbuffertag:= 0-fclearbuffertag;
終わり;
手順tchatroom.onespeak(content:string);
始める
群れ:= true;
inc(fbufferlength);
fbufferlength> 20の場合
始める
ClearBuffer;
inc(fbufferlength);
終わり;
fbuffer [fbufferlength]:= content;
群れ:= false;
終わり;
function tchatroom.oneread:tstrings;
var
fstrings:tstrings;
I:整数;
始める
群れ:= true;
fstrings:= tstringlist.create;
i:= 1からfbufferlengthの場合
fstrings.add(fbuffer [i]);
結果:= fstrings;
群れ:= false;
終わり;
function tchatroom.getcanread:boolean;
始める
結果:= false;
fbufferlength> 0の場合、結果:= true;
終わり;
手順tchatroom.loginroom(username:string);
//ユーザーログインチャットルームイベントはここに完全に実装されていません
始める
Inc(fconnectCount);
終わり;
手順tchatroom.leaveroom(username:string);
//ユーザーはチャットルームイベントを去りますが、ここでは完全には実装されていません
始める
12月(fconnectCount);
終わり;
サーバー側の最後の重要な部分tchatroommanager:
タイプ
tchatroommanager = class
プライベート
チャットルーム:tchatroomの配列。
公共
コンストラクターCREATE;
function findroombyid(id:integer):tchatroom;
終わり;
実装部分:
{tchatroommanager}
Constructor tchatroommanager.create;
var
私、ルームカウント:整数;
ルームネーム:tstrings; //ルームネームは構成ファイルのチャットルーム名です
始める
ルームカウント:= 1;
//ここで、構成ファイルからいくつかのチャットルームを読み取ります。
roomnames:= tstringlist.create;
roomnames.add( 'testroom'); //この文は、構成ファイルからの最終的な読み取りに置き換えられます。
setLength(チャットルーム、ルームカウント);
i:= 1 to roomcountの場合
チャットルーム[i]:= tchatroom.create(roomnames [i-1]、i);
終わり;
function tchatroommanager.findroombyid(id:integer):tchatroom;
//この関数は、インターフェイスの最終バージョンが顧客に提供されるため、iChatmanagerインターフェイスによって呼び出されます。
//部屋リストを取得する機能は、クライアントがその部屋のIDを知っているので
始める
結果:=チャットルーム[ID];
終わり;
初期化
チャットルームマネージャー:= tchatroommanager.create;
終わり。
サーバー側のメインコア部分が完了した後、サーバー側のDCOM構成を構成し、テスト用の簡単なクライアントを開発できます。サーバー側のタイプをコピーする必要があります。TLBは、もちろんクライアントを登録した後にのみ開発および使用できます。
クライアントでは、2つの比較的重要な機能のみをリストし、残りはすべてのプログラムを取得するために書いてください。
手順tform1.button1click(sender:tobject);
// button1をクリックし、編集のコンテンツを「発言」します
始める
server.speakto(edit1.text、1);
終わり;
手順tform1.timer1timer(sender:tobject);
//サーバーから時々会話のコンテンツをリクエストし、1.5秒に設定します
var
TempStrings:Tstrings;
I:整数;
始める
server.ready(1)= 1の場合
始める
TempStrings:= tstringlist.create;
setolestrings(tempstrings、server.readfrom(1));
freadstartpos> 19の場合
if(fclearbuffertag = 0-server.testclearbuffertag(1))then
始める
freadstartpos:= 0;
fclearbuffertag:= server.testclearbuffertag(1);
終わり;
i:= freadstartpos to tempstrings.count-1 do
memo1.lines.add(tempstrings [i]);
freadstartpos:= tempstrings.count;
終わり;
終わり;
DCOMベースのLANチャットルームのコア部分は基本的に完了しており、すべてのテストは比較的スムーズです。チャットルームサーバーの難しさを追加する必要があります。また、一定の同期処理がありますが、このプログラムがさらに多くのテストを必要とする場合、デッドロックまたは他のライブロックが発生する場合があります。