пʼятниця, 17 січня 2025 р.

 Програми Сервера та Клієнта на Delphi з кодами

 


Привіт всім! Після Різдвяних та Новорічних свят продовжив свої експерименти в Делфі. Цього разу хочу поділитися своїми напрацюваннями у створенні програм сервера та клієнта з кодами цих програм.

По перше - це програма Серверу. Програма реалізована з використанням компонентів IdIPWatch та TServerSocet щодо роботи в локальній мережі. Приводжу повний код цієї програми для інтерфейсу, який зображено на першому рисунку:

============ Code of the Server program =========

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ScktComp, Spin, ExtCtrls, ComCtrls, IdGlobal, StrUtils,

  IdStack, IdSocketHandle, IdIPAddress, IdBaseComponent, IdComponent, IdIPWatch;


type

  TForm1 = class(TForm)

    SpinEdit1: TSpinEdit; // SpinEdit to select server port

    ServerSocket1: TServerSocket; // ServerSocket component for handling server connections

    btn1: TButton; // Button to start the server

    btn2: TButton; // Button to stop the server

    Edit1: TEdit; // Edit box for entering messages

    Lbl2: TLabel; // Label for displaying IP address

    Panel1: TPanel; // Panel for displaying server status

    Btn3: TButton; // Button to clear the log

    Lbl3: TLabel; // Label for displaying messages

    RichEdit1: TRichEdit; // RichEdit to display log messages

    Button1: TButton; // Button to display local IP address

    IdIPWatch1: TIdIPWatch; // Component to watch IP address changes

    procedure btn1Click(Sender: TObject); // Procedure to start the server

    procedure btn2Click(Sender: TObject); // Procedure to stop the server

    procedure Edit1KeyPress(Sender: TObject; var Key: Char); // Procedure to handle Enter key press in Edit1

    procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); // Procedure to handle data read from clients

    procedure ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); // Procedure to handle client disconnection

    procedure FormCreate(Sender: TObject); // Procedure to initialize the form

    procedure FormClose(Sender: TObject; var Action: TCloseAction); // Procedure to handle form close event

    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); // Procedure to handle form close query event

    procedure ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); // Procedure to handle client connection

    procedure Btn3Click(Sender: TObject); // Procedure to clear the log

    procedure SpinEdit1Change(Sender: TObject); // Procedure to handle changes in SpinEdit1

    procedure Button1Click(Sender: TObject); // Procedure to display local IP address


  private

    Clients: TList; // List to keep track of connected clients

    procedure BroadcastMessage(const AMsg: string; ASenderSocket: TCustomWinSocket); // Procedure to broadcast messages to all clients

  public

    { Public declarations }

  end;


var

  Form1: TForm1;

  UTC: tSystemTime; // Variable to store UTC date & time

  TimeNow: string; // Variable to store current time as a string


implementation


{$R *.dfm}


// Procedure to initialize the form

procedure TForm1.FormCreate(Sender: TObject);

begin

  Clients := TList.Create; // Initialize the clients list

  RichEdit1.Clear; // Clear the RichEdit

  Edit1.Clear; // Clear the Edit1

  Edit1.Enabled := False; // Disable Edit1 initially

  btn1.Enabled := True; // Enable the start button

  btn2.Enabled := False; // Disable the stop button

  Panel1.Font.Color := clRed; // Set the panel font color to red

  Panel1.Caption := 'Server OFF'; // Set the initial server status

end;

// Procedure to display local IP address

procedure TForm1.Button1Click(Sender: TObject);

begin

  RichEdit1.Lines.Add(IdIPWatch1.LocalIP); // Add the local IP address to the RichEdit

end;

// Procedure to start the server

procedure TForm1.btn1Click(Sender: TObject);

begin

  ServerSocket1.Port := SpinEdit1.Value; // Set the server port

  ServerSocket1.Active := True; // Activate the server

  btn2.Enabled := True; // Enable the stop button

  btn1.Enabled := False; // Disable the start button

  Panel1.Font.Color := clNavy; // Set the panel font color to navy

  Panel1.Caption := 'Server ON'; // Set the server status to ON

end;

// Procedure to stop the server

procedure TForm1.btn2Click(Sender: TObject);

begin

  ServerSocket1.Active := False; // Deactivate the server

  btn1.Enabled := True; // Enable the start button

  btn2.Enabled := False; // Disable the stop button

  Panel1.Font.Color := clRed; // Set the panel font color to red

  Panel1.Caption := 'Server OFF'; // Set the server status to OFF

  Edit1.Enabled := False; // Disable Edit1

end;

// Procedure to handle Enter key press in Edit1

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

var

  S: string;

begin

  if Key = Chr(13) then // If Enter key is pressed

  begin

    Key := Chr(0); // Reset the key

    S := Edit1.Text; // Get the text from Edit1


    try

      // Broadcast the message to all connected clients

      BroadcastMessage(S, nil);

    finally

      Edit1.Clear; // Clear the Edit1

      GetSystemTime(UTC); // Get the current UTC time

      TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

      RichEdit1.SelAttributes.Color := clRed; // Set the text color to red

      RichEdit1.Lines.Add(TimeNow + ' TX> ' + S); // Add the message to the RichEdit

      Edit1.SetFocus; // Set focus back to Edit1

    end;

  end;

end;

// Procedure to broadcast messages to all clients

procedure TForm1.BroadcastMessage(const AMsg: string; ASenderSocket: TCustomWinSocket);

var

  i: Integer;

  ClientSocket: TCustomWinSocket;

begin

  for i := 0 to ServerSocket1.Socket.ActiveConnections - 1 do

  begin

    ClientSocket := ServerSocket1.Socket.Connections[i];

    if ClientSocket <> ASenderSocket then

      ClientSocket.SendText(AMsg);

  end;

end;

// Procedure to handle client connection

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);

begin

  Clients.Add(Socket); // Add the client socket to the clients list

  GetSystemTime(UTC); // Get the current UTC time

  TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

  RichEdit1.SelAttributes.Color := clMaroon; // Set the text color to maroon

  RichEdit1.Lines.Add(TimeNow + ' Client ' + IntToHex(Integer(Socket), 8) + ' connected'); // Add the connection message to the RichEdit

  Edit1.Enabled := True; // Enable Edit1

  Edit1.SetFocus; // Set focus to Edit1

end;

// Procedure to handle data read from clients

procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);

var

  Received: string;

  r: TStringList;

begin

  Received := Socket.ReceiveText; // Receive text from the client

  GetSystemTime(UTC); // Get the current UTC time

  TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

  RichEdit1.SelAttributes.Color := clBlue; // Set the text color to blue

  RichEdit1.Lines.Add(TimeNow + ' RX from ' + IntToHex(Integer(Socket), 8) + ' > ' + Received); // Add the received message to the RichEdit

  Socket.SendText('CFM "' + Received + '"'); // Send confirmation to the client

  BroadcastMessage(Received, Socket); // Broadcast the received message to other clients


  // Log the received message to a file

  r := TStringList.Create;

  try

    if FileExists('log.txt') then

      r.LoadFromFile('log.txt');

    r.Add(TimeNow + ' > ' + Received);

    r.SaveToFile('log.txt');

  finally

    r.Free;

  end;

end;

// Procedure to handle client disconnection

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);

begin

  GetSystemTime(UTC); // Get the current UTC time

  TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

  Clients.Remove(Socket); // Remove the client socket from the clients list

  RichEdit1.SelAttributes.Color := clMaroon; // Set the text color to maroon

  RichEdit1.Lines.Add(TimeNow + ' Client ' + IntToHex(Integer(Socket), 8) + ' disconnected'); // Add the disconnection message to the RichEdit

end;

// Procedure to clear the log

procedure TForm1.Btn3Click(Sender: TObject);

begin

  RichEdit1.Clear; // Clear the RichEdit

end;

// Procedure to handle form close event

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  ServerSocket1.Active := False; // Deactivate the server

end;

// Procedure to handle form close query event

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

  ServerSocket1.Active := False; // Deactivate the server

end;

// Procedure to handle changes in SpinEdit1

procedure TForm1.SpinEdit1Change(Sender: TObject);

begin

  btn2.Click; // Stop the server

  btn1.Click; // Start the server with the new port

end;

end.

Для роботи з Сервером використовується програма Клієнта, інтерфейс якої зображено на другому рисунку. 

Програма реалізована з використанням компоненту TClientSocet щодо роботи в локальній мережі.

 Приводжу повний код програми Клієнта:

=============== Code of the Client program ============

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, Spin, ScktComp, ComCtrls, ExtCtrls;


type

  TForm1 = class(TForm)

    ClientSocket1: TClientSocket; // Client socket component for managing the client-server connection

    edt1: TEdit; // Edit box for entering the server address

    se1: TSpinEdit; // Spin edit for entering the server port

    btn1: TButton; // Button for connecting to the server

    edt2: TEdit; // Edit box for entering the message to send

    Lbl1: TLabel; // Label for server address

    Lbl2: TLabel; // Label for server port

    Lbl3: TLabel; // Label for message input

    Btn2: TButton; // Button for disconnecting from the server

    Panel1: TPanel; // Panel for displaying connection status

    RichEdit1: TRichEdit; // Rich edit box for displaying messages

    Btn3: TButton; // Button for clearing the message box

    procedure btn1Click(Sender: TObject); // Event handler for the connect button click

    procedure edt2KeyPress(Sender: TObject; var Key: Char); // Event handler for key press in the message input box

    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); // Event handler for reading data from the server

    procedure FormCreate(Sender: TObject); // Event handler for form creation

    procedure Btn2Click(Sender: TObject); // Event handler for the disconnect button click

    procedure FormClose(Sender: TObject; var Action: TCloseAction); // Event handler for form close

    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); // Event handler for form close query

    procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); // Event handler for successful connection to the server

    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); // Event handler for socket errors

    procedure ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket); // Event handler for disconnection from the server

    procedure Btn3Click(Sender: TObject); // Event handler for the clear button click

    procedure FormShow(Sender: TObject); // Event handler for form show


  private

    { Private declarations }

  public

    { Public declarations }

  end;


var

  Form1: TForm1;

  UTC: tSystemTime; // Variable to store UTC date & time

  TimeNow: string; // Variable to store current time as a string


implementation


{$R *.dfm}


// This procedure is called when the form is created. It initializes the user interface.

procedure TForm1.FormCreate(Sender: TObject);

begin

  RichEdit1.Clear; // Clear the messages box

  edt2.Enabled := False; // Disable the message input box until connected to the server

  Btn2.Enabled := False; // Disable the disconnect button until connected to the server

  Panel1.Font.Color := clNavy; // Set the panel font color

  Panel1.Caption := 'Waiting for a connection to the server'; // Display the initial status message

end;

// This procedure is called when the connect button is clicked. It attempts to connect to the server.

procedure TForm1.btn1Click(Sender: TObject);

begin

  ClientSocket1.Host := edt1.Text; // Set the server address from the input box

  ClientSocket1.Port := se1.Value; // Set the server port from the spin edit

  ClientSocket1.Open; // Open the connection to the server

end;

// This procedure is called when a key is pressed in the message input box. It sends the message if Enter is pressed.

procedure TForm1.edt2KeyPress(Sender: TObject; var Key: Char);

var

  Msg: string; // Variable to store the message

begin

  if edt2.Text = '' then Exit; // Exit if the input box is empty

  if Key = #13 then // Check if Enter key is pressed

  begin

    Key := #0; // Reset the key press

    Msg := edt2.Text; // Store the message from the input box

    try

      ClientSocket1.Socket.SendText(Msg); // Send the message to the server

      GetSystemTime(UTC); // Get the current UTC time

      TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

      RichEdit1.SelAttributes.Color := clRed; // Set the text color for sent messages

      RichEdit1.Lines.Add(TimeNow + ' TX> ' + Msg); // Add the sent message to the messages box

    finally

      edt2.Clear; // Clear the input box

      edt2.SetFocus; // Set focus back to the input box

    end;

  end;

end;

// This procedure is called when data is received from the server. It displays the received message.

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

begin

  GetSystemTime(UTC); // Get the current UTC time

  TimeNow := Format('%.2d', [UTC.wHour]) + ':' + Format('%.2d', [UTC.wMinute]); // Format the time as a string

  RichEdit1.SelAttributes.Color := clBlue; // Set the text color for received messages

  RichEdit1.Lines.Add(TimeNow + ' RX> ' + Socket.ReceiveText); // Add the received message to the messages box

end;

// This procedure is called when the disconnect button is clicked. It closes the connection to the server.

procedure TForm1.Btn2Click(Sender: TObject);

begin

  ClientSocket1.Close; // Close the connection to the server

end;

// This procedure is called when the form is closing. It ensures the connection to the server is closed.

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  ClientSocket1.Close; // Close the connection to the server

end;

// This procedure is called when the form is queried for closing. It ensures the connection to the server is closed.

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

  ClientSocket1.Close; // Close the connection to the server

end;

// This procedure is called when a connection to the server is successfully established.

procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);

begin

  Panel1.Font.Color := clNavy; // Set the panel font color

  Panel1.Caption := 'Connected!'; // Display the connection status

  edt2.Enabled := True; // Enable the message input box

  btn1.Enabled := False; // Disable the connect button

  Btn2.Enabled := True; // Enable the disconnect button

  edt2.SetFocus; // Set focus to the message input box

end;

// This procedure is called when an error occurs in the socket connection. It displays an error message.

procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

begin

  Panel1.Font.Color := clRed; // Set the panel font color

  Panel1.Caption := 'Connection error!'; // Display the error message

  ErrorCode := 0; // Reset the error code

end;

// This procedure is called when the connection to the server is disconnected.

procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);

begin

  Panel1.Font.Color := clRed; // Set the panel font color

  Panel1.Caption := 'Connection broken!'; // Display the disconnection status

  edt2.Enabled := False; // Disable the message input box

  btn1.Enabled := True; // Enable the connect button

  Btn2.Enabled := False; // Disable the disconnect button

end;

// This procedure is called when the clear button is clicked. It clears the messages box.

procedure TForm1.Btn3Click(Sender: TObject);

begin

  RichEdit1.Clear; // Clear the messages box

end;

// This procedure is called when the form is shown. It sets the initial focus to the server address input box.

procedure TForm1.FormShow(Sender: TObject);

begin

  edt1.SetFocus; // Set focus to the server address input box

  edt1.SelStart := edt1.SelLength + 1; // Set the cursor to the end of the input text

  edt2.Clear; // Clear the message input box

end;

end.

Сподіваюся, що ця інформація стане в нагоді тим, хто займається створенням програм для  обміну даними в локальних мережах.

Так виглядає робота програми Серверу і двох програм Клієнтів у мережі.


Мої найкращі побажання відвідувачам мого блогу! Всім мирного неба над головою! 73!

Немає коментарів:

Дописати коментар