Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Socket C&S (https://www.delphipraxis.net/195149-socket-c-s.html)

Zacherl 9. Feb 2018 20:24

AW: Socket C&S
 
Also tatsächlich nonblocking Sockets?

Eine Sache, die mir grade noch auffällt, ist das Speichern/Laden des Bitmaps. Gibt es einen Grund, warum du nicht z.b.
Delphi-Quellcode:
TMemoryStream
verwendest? Dann reduziert sich dein kompletter Code mit den
Delphi-Quellcode:
ScanLine
s nämlich auf ein
Delphi-Quellcode:
I := 1234;
Stream.Write(I);
Bitmap.SaveToStream(Stream)
analog dazu das Laden:
Delphi-Quellcode:
Stream.Read(I);
if (I = 1234) then
  Bitmap.LoadFromStream(Stream)

scrat1979 9. Feb 2018 20:37

AW: Socket C&S
 
Ich kann dir die sgcWebSockets nur wärmstens empfehlen. Damit habe ich mir innerhalb von paar Stunden meinen eigenen Server und Client abgeleitet und jetzt wird er für einen netzwerkfähigen Terminkalender verwendet. Einfach klasse!

tomkupitz 9. Feb 2018 21:07

AW: Socket C&S
 
Zitat:

Also tatsächlich nonblocking Sockets?
ja, nonblocking.

Zitat:

Gibt es einen Grund, warum du nicht z.b. TMemoryStream verwendest?
nein, habe ich nur zu Testzwecken verwendet, ist also noch nicht "optimiert".

Zacherl 9. Feb 2018 23:31

AW: Socket C&S
 
So in etwa würde ich vorgehen, um direkt nach dem Connecten einen simplen String an den Server zu schicken (btw. die Socket Komponenten sind schon sehr lange deprecated und evtl. könnten blocking Sockets hier für dich auch besser geeignet sein):
Delphi-Quellcode:
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Win.ScktComp;

type
  TSocketBufferDataEvent =
    procedure (Sender: TOBject; Socket: TCustomWinSocket; const Data: TBytes) of Object;

  TSocketBuffer = class(TObject)
  strict private
    FBuffer: TMemoryStream;
    FLength: UInt32;
  strict private
    FOnData: TSocketBufferDataEvent;
  public
    procedure Receive(Socket: TCustomWinSocket);
  public
    constructor Create;
    destructor Destroy; override;
  public
    property OnData: TSocketBufferDataEvent read FOnData write FOnData;
  end;

  TForm2 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  strict private
    FClient: TClientSocket;
    FClientBuffer: TSocketBuffer;
    FServer: TServerSocket;
  strict private
    procedure Send(Socket: TCustomWinSocket; const Data: TBytes);
  strict private
    procedure ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientData(Sender: TOBject; Socket: TCustomWinSocket; const Data: TBytes);
    procedure ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure ServerData(Sender: TOBject; Socket: TCustomWinSocket; const Data: TBytes);
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

uses
  System.Math;

{$R *.dfm}

{ TSocketBuffer }

constructor TSocketBuffer.Create;
begin
  inherited Create;
  FBuffer := TMemoryStream.Create;
  FLength := 0;
end;

destructor TSocketBuffer.Destroy;
begin
  FBuffer.Free;
  inherited;
end;

procedure TSocketBuffer.Receive(Socket: TCustomWinSocket);
type
  PUInt32 = ^UInt32;
var
  B: array[0..64*1024 - 1] of Byte;
  N: UInt32;
  D: TBytes;
begin
  // Erstmal alle Daten in den Buffer schreiben
  while (Socket.ReceiveLength > 0) do
  begin
    N := System.Math.Min(Socket.ReceiveLength, Length(B));
    Socket.ReceiveBuf(B[0], N);
    FBuffer.Write(B[0], N);
    Inc(FLength, N);
  end;

  // Pakete parsen
  while (FLength >= SizeOf(N)) do
  begin
    N := PUInt32(FBuffer.Memory)^;
    if (FLength < SizeOf(N) + N) then
    begin
      Break;
    end;
    // Mindestens ein Paket vollständig angekommen
    SetLength(D, N);
    CopyMemory(@D[0], PByte(FBuffer.Memory) + SizeOf(N), N);
    if Assigned(FOnData) then
    begin
      FOnData(Self, Socket, D);
    end;

    // Jetzt muss das bearbeitete Paket aus dem Buffer "entfernt" werden
    CopyMemory(FBuffer.Memory, PByte(FBuffer.Memory) + SizeOf(N) + N, FLength - SizeOf(N) - N);
    Dec(FLength, SizeOf(N) + N);
    FBuffer.Position := FBuffer.Position - SizeOf(N) - N;
  end;
end;

{ TForm2 }

procedure TForm2.Button1Click(Sender: TObject);
begin
  FClient.Active := true;
end;

procedure TForm2.ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Send(Socket, TEncoding.UTF8.GetBytes('This is a test string'));
end;

procedure TForm2.ClientData(Sender: TOBject; Socket: TCustomWinSocket; const Data: TBytes);
begin
  // Vollständiges Paket vom Server empfangen

end;

procedure TForm2.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  FClientBuffer.Receive(Socket);
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  FClient := TClientSocket.Create(Self);
  FClient.ClientType := ctNonBlocking;
  FClient.Host := 'localhost';
  FClient.Port := 12345;
  FClient.OnConnect := ClientConnect;
  FClient.OnRead := ClientRead;
  FClientBuffer := TSocketBuffer.Create;
  FClientBuffer.OnData := ClientData;
  FServer := TServerSocket.Create(Self);
  FServer.ServerType := stNonBlocking;
  FServer.Port := 12345;
  FServer.OnClientConnect := ServerClientConnect;
  FServer.OnClientDisconnect := ServerClientDisconnect;
  FServer.OnClientRead := ServerRead;
  FServer.Active := true;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  FClientBuffer.Free;
end;

procedure TForm2.Send(Socket: TCustomWinSocket; const Data: TBytes);
var
  N, S: UInt32;
begin
  N := Length(Data);
  S := 0;
  Assert(Socket.SendBuf(N, SizeOf(N)) = 4);
  while (S < N) do
  begin
    Inc(S, Socket.SendBuf(Data[S], N - S));
  end;
end;

procedure TForm2.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  Buffer: TSocketBuffer;
begin
  Buffer := TSocketBuffer.Create;
  Buffer.OnData := ServerData;
  Socket.Data := Buffer;
end;

procedure TForm2.ServerClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  TSocketBuffer(Socket.Data).Free;
end;

procedure TForm2.ServerData(Sender: TOBject; Socket: TCustomWinSocket; const Data: TBytes);
begin
  // Vollständiges Paket vom Client empfangen
  Caption := TEncoding.UTF8.GetString(Data);
end;

procedure TForm2.ServerRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  TSocketBuffer(Socket.Data).Receive(Socket);
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:53 Uhr.
Seite 3 von 3     123   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz