首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 基於 DCOM 開發區域網路聊天室:服務端與客戶端架構設計

     編輯:Delphi

架構設計

  • DCOM (Distributed COM):讓客戶端透過 RPC 遠端呼叫伺服器端物件方法,無需撰寫 Socket 程式碼。
  • 介面 IChatManager:定義 SpeakTo、ReadFrom、ConnectRoom、DisconnectRoom、ReadReady、TestClearBufferTag。
  • 伺服器端物件:TChatManager (實作 IChatManager)、TChatRoomManager (管理多聊天室)、TChatRoom (單一聊天室緩衝區與同步鎖)。
  • 客戶端:透過型別庫匯入介面,定時輪詢 ReadReady → ReadFrom 顯示訊息。

核心介面定義 (IDL/Type Library)

[
  uuid(E7CD7F0D-447F-497A-8C7B-1D80E748B67F),
  dual, oleautomation
]
interface IChatManager : IDispatch {
  [id(1)] HRESULT SpeakTo([in] BSTR content, [in] long destid);
  [id(2)] HRESULT ReadFrom([in] long sourceid, [out, retval] IStrings** result);
  [id(3)] HRESULT ReadReady([in] long id, [out, retval] Byte* result);
  [id(4)] HRESULT ConnectRoom([in] BSTR UserName, [in] long RoomID);
  [id(5)] HRESULT DisconnectRoom([in] BSTR UserName, [in] long RoomID);
  [id(6)] HRESULT TestClearBufferTag([in] long RoomID, [out, retval] long* result);
};

伺服器端關鍵實作重點

TChatRoom - 緩衝區與同步

type
  TChatRoom = class
  private
    FBuffer: array[1..20] of string; // 環狀緩衝區
    FBufferLength, FRoomID, FClearBufferTag: Integer;
    FLocked: Boolean; // 簡易自旋鎖
    FRoomName: string;
  public
    constructor Create(const RoomName: string; RoomID: Integer);
    procedure OneSpeak(const Content: string);
    function OneRead: IStrings; // 回傳介面供跨進程封送
    procedure LoginRoom(const UserName: string);
    procedure LeaveRoom(const UserName: string);
    property Locked: Boolean read FLocked;
    property CanRead: Boolean read GetCanRead;
    property ClearBufferTag: Integer read FClearBufferTag;
  end;

procedure TChatRoom.OneSpeak(const Content: string);
begin
  // 簡易自旋等待鎖 (實務應用 Critical Section 或 Mutex)
  while FLocked do Sleep(1);
  FLocked := True;
  try
    Inc(FBufferLength);
    if FBufferLength > 20 then ClearBuffer;
    FBuffer[FBufferLength] := Content;
  finally
    FLocked := False;
  end;
end;

TChatManager - 介面方法轉發

function TChatManager.SpeakTo(const Content: WideString; DestID: Integer): HResult;
var
  Room: TChatRoom;
begin
  Room := ChatRoomManager.FindRoomByID(DestID);
  if Assigned(Room) then
  begin
    Room.OneSpeak(Content);
    Result := S_OK;
  end
  else Result := E_INVALIDARG;
end;

function TChatManager.ReadFrom(SourceID: Integer): IStrings;
var
  Room: TChatRoom;
  StrList: TStringList;
begin
  Room := ChatRoomManager.FindRoomByID(SourceID);
  if Assigned(Room) then
  begin
    while Room.Locked do Sleep(1);
    StrList := TStringList.Create;
    try
      Room.OneRead(StrList); // 填充 StrList
      Result := StrList as IStrings; // 自動封送
    except
      StrList.Free;
      raise;
    end;
  end
  else Result := nil;
end;

客戶端輪詢邏輯

procedure TFormClient.TimerPollTimer(Sender: TObject);
var
  Strs: IStrings;
  i: Integer;
begin
  if ChatServer.ReadReady(CurrentRoomID) = 1 then
  begin
    Strs := ChatServer.ReadFrom(CurrentRoomID);
    if Assigned(Strs) then
    begin
      for i := FLastReadIndex to Strs.Count - 1 do
        MemoChat.Lines.Add(Strs[i]);
      FLastReadIndex := Strs.Count;
    end;
  end;
end;

部署與設定步驟

  1. 伺服器專案建立 COM+ 應用程式 (元件服務),註冊 TChatManager 為 MultiInstance、Apartment 執行緒模型。
  2. 客戶端機器:複製型別庫 (.tlb) 並執行 regsvr32 ChatServer.tlb,或在 Delphi 專案 Import Type Library 產生介面單元。
  3. DCOM 設定 (dcomcnfg):元件 → 內容 → 身分識別 (互動使用者/特定帳號) → 安全性 → 啟動及啟用權限/存取權限 → 加入 Everyone/網路用戶允許。
  4. 防火牆開放 RPC 動態連接埠範圍 (預設 49152-65535) 或設定固定端點。

同步與擴展性提醒

  • 原始碼使用 while Locked do Sleep(1) 忙碌等待,高併發下極度低效,實務必須使用 TCriticalSection、TMonitor、Named Mutex 或無鎖佇列。
  • DCOM 預設每個呼叫建立獨立執行緒 (Apartment 模型),伺服器需妥善管理執行緒池與物件生命週期。
  • 現代替代方案:DataSnap (TCP/HTTP/HTTPs)、gRPC、WebSocket (sgcWebSockets)、REST + SignalR,跨平台、防火牆友善、易於維運。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved