Програми Сервера та Клієнта на 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!