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

Delphi 使用 UDP (Indy NMUDP) 實作區域網路聊天室:廣播與私訊

     編輯:Delphi

架構概覽

  • 協定:UDP (無連線、低延遲、支援廣播)。
  • 元件:Indy TIdUDPClient / TIdUDPServer (舊版為 TNMUDP)。
  • 通訊埠:雙方同一 Port (預設 8888)。
  • 訊息格式:電腦名: 內容,廣播送給列表所有線上使用者,私訊僅送給選取目標。

關鍵程式碼結構

// 發送訊息 (廣播或私訊)
procedure TForm1.SendChat(const Text: string; Broadcast: Boolean);
var
  Stream: TMemoryStream;
  i: Integer;
begin
  if Text = '' then Exit;
  Stream := TMemoryStream.Create;
  try
    Stream.WriteBuffer(Text[1], Length(Text));
    if Broadcast then
    begin
      for i := 1 to ListBoxUsers.Items.Count - 1 do // 索引 0 為「所有人」
      begin
        IdUDPClient1.Host := ListBoxUsers.Items[i];
        IdUDPClient1.Send(Stream);
      end;
    end
    else
    begin
      IdUDPClient1.Host := ListBoxUsers.Items[ListBoxUsers.ItemIndex];
      IdUDPClient1.Send(Stream);
    end;
  finally
    Stream.Free;
  end;
end;

// 接收訊息 (OnUDPRead 事件)
procedure TForm1.IdUDPClient1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  S: string;
begin
  SetLength(S, AData.Size);
  AData.ReadBuffer(S[1], AData.Size);
  MemoChat.Lines.Add(S); // 直接顯示「電腦名: 內容」
end;

使用者列表管理

  • 啟動時取得本機電腦名稱 (GetComputerName) 加入列表,並加入「所有人」項目。
  • 提供「新增使用者」輸入 IP/電腦名,「移除使用者」從列表刪除 (不可刪除「所有人」)。

完整表單單元 (精簡版)

unit ChatMain;

interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, IdUDPServer;

type
  TFormChat = class(TForm)
    IdUDPClient1: TIdUDPClient;
    IdUDPServer1: TIdUDPServer;
    ListBoxUsers: TListBox;
    MemoChat: TMemo;
    EditMsg: TEdit;
    btnSend: TButton;
    btnBroadcast: TButton;
    btnAddUser: TButton;
    btnRemoveUser: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
    procedure btnBroadcastClick(Sender: TObject);
    procedure btnAddUserClick(Sender: TObject);
    procedure btnRemoveUserClick(Sender: TObject);
    procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
  private
    procedure SendMsg(const Text: string; Broadcast: Boolean);
  end;

var
  FormChat: TFormChat;

implementation
{$R *.dfm}

procedure TFormChat.FormCreate(Sender: TObject);
var
  NameBuf: array[0..255] of Char;
  Size: DWORD;
begin
  Size := Length(NameBuf);
  GetComputerName(NameBuf, Size);
  ListBoxUsers.Items.Add('所有人');
  ListBoxUsers.Items.Add(StrPas(NameBuf));
  ListBoxUsers.ItemIndex := 0;

  IdUDPServer1.DefaultPort := 8888;
  IdUDPServer1.Active := True;
  IdUDPClient1.Port := 8888;
end;

procedure TFormChat.SendMsg(const Text: string; Broadcast: Boolean);
var
  Stream: TMemoryStream;
  i: Integer;
begin
  if Trim(Text) = '' then Exit;
  Stream := TMemoryStream.Create;
  try
    Stream.WriteBuffer(Text[1], Length(Text));
    if Broadcast then
    begin
      for i := 1 to ListBoxUsers.Items.Count - 1 do
      begin
        IdUDPClient1.Host := ListBoxUsers.Items[i];
        IdUDPClient1.Send(Stream);
        Stream.Position := 0; // 重置位置供下次發送
      end;
    end
    else if ListBoxUsers.ItemIndex > 0 then
    begin
      IdUDPClient1.Host := ListBoxUsers.Items[ListBoxUsers.ItemIndex];
      IdUDPClient1.Send(Stream);
    end;
  finally
    Stream.Free;
  end;
  EditMsg.Clear;
  EditMsg.SetFocus;
end;

procedure TFormChat.btnSendClick(Sender: TObject);
begin
  SendMsg(Format('%s: %s', [ListBoxUsers.Items[1], EditMsg.Text]), False);
end;

procedure TFormChat.btnBroadcastClick(Sender: TObject);
begin
  SendMsg(Format('%s: %s', [ListBoxUsers.Items[1], EditMsg.Text]), True);
end;

procedure TFormChat.btnAddUserClick(Sender: TObject);
var
  S: string;
begin
  S := InputBox('新增使用者', '輸入電腦名或 IP', '');
  if S <> '' then ListBoxUsers.Items.Add(S);
end;

procedure TFormChat.btnRemoveUserClick(Sender: TObject);
begin
  if ListBoxUsers.ItemIndex > 0 then
    ListBoxUsers.Items.Delete(ListBoxUsers.ItemIndex);
end;

procedure TFormChat.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  S: string;
begin
  SetLength(S, AData.Size);
  AData.ReadBuffer(S[1], AData.Size);
  MemoChat.Lines.Add(S);
end;

end.

部署注意事項

  • 所有參與聊天的電腦需在同一區域網路,且防火牆開放 UDP 8888。
  • 若跨網段,需路由器開啟 UDP 廣播轉發或改用伺服器轉發架構 (TCP/HTTP)。
  • Indy 10+ 版本請使用 TIdUDPClient/TIdUDPServer,舊版 TNMUDP 已棄用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved