Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi RecordtoString (https://www.delphipraxis.net/72039-recordtostring.html)

arbu man 24. Jun 2006 11:34


RecordtoString
 
Hi,

ich kann mit dem UDPSockUtil Texte mit einer Länge von bis zu einer länge von 512 Byte verschicken, leider nützen mir texte herzlich wenig, da das parsen zu (zeit)aufwändig wäre. Was ich gerne verschicken würde wären records mit kleinen string (string[20]) und zahlen (integer, double). leider weiss ich zwei Sachen nicht wie wandle ich einen record in einen string um und wie wieder zurück.

mfg, Björn

andreash 24. Jun 2006 12:18

Re: RecordtoString
 
Hallo,

mir fallen verschiedene Möglichkeiten ein:
  • Schreibe die Felder deines Records in einen String, wobei du die Werte der Felder mit einem Trennzeichen trennst.
  • Verwende die Funktionen BinToHex und HexToBin; Nachteil: Der String wird doppelt so lang wie die Länge des Records
  • Verwende Base64 Routinen (Unter dem Stichwort Base64 findest du in diesem Forum einige Einträge)

Union 24. Jun 2006 12:25

Re: RecordtoString
 
Schau mal unter Delphi-Referenz durchsuchenMove oder Delphi-Referenz durchsuchenabsolute nach.

arbu man 24. Jun 2006 13:08

Re: RecordtoString
 
hey Danke Move sieht wunderbar aus :)

SirThornberry 24. Jun 2006 13:19

Re: RecordtoString
 
move sollte die beste lösung sein:
Delphi-Quellcode:
SetLength(DeinString, SizeOf(DeinRecord));
move(DeinRecord, DeinString[1], SizeOf(DeinRecord));

Union 24. Jun 2006 13:23

Re: RecordtoString
 
Ja, aber Achtung: Das geht nur bis zu 255 Byte String/Pufferlänge! Alternative eben auch absolute, das ist dann für ganz Faule ;) - Ausser bei der Deklaration

Delphi-Quellcode:
procedure DoSomethingWithTheBuffer;
type
   // Buffer als Stringimitat
   TBuffer = record
      BufferLength : byte;
      BufferContents : array[0..255] of byte;
   end;
var
   Buffer : TBuffer;
   BufferString : string absolute Buffer;
begin
   // Irgendwas passiert mit den Buffercontents
   // ... Länge der Nutzdaten eintragen
   Buffer.BufferLength := 123;
   // Jetzt können wir auf den String zugreifen, denn Buffer.BufferLength = Bufferstring[0]
   // Dadurch braucht man kein Move, denn die Variablen liegen "übereinander" auf der selben Adresse.
end;

Hawkeye219 24. Jun 2006 14:12

Re: RecordtoString
 
@Union:
Das "Achtung" gilt aber auch für dich: dein Code funktioniert nämlich nur mit ShortString, Delphi benutzt aber normalerweise lange (dynamische) Strings, bei denen es keine Längenbeschränkung auf 255 Zeichen gibt. In deinem Code ist BufferString also ein Zeiger mit einer Länge von 4 Bytes, den man wohl nicht mit TBuffer gleichsetzen sollte...

Gruß Hawkeye

Union 24. Jun 2006 14:20

Re: RecordtoString
 
:oops: Ja, Du hast Recht. In der Deklaration sollte Shortstring als Typenbezeichner stehen.

arbu man 24. Jun 2006 14:28

Re: RecordtoString
 
Was mich jetzt noch interessieren würde warum geht es nur bis 255 ?

Hawkeye219 24. Jun 2006 14:32

Re: RecordtoString
 
Mit der folgenden Record-Definition gibt's weniger Probleme:

Delphi-Quellcode:
TBuffer = packed record
  BufferLength  : byte;
  BufferContents : array [1..255] of byte;
end;
Zurück zum eigentlichen Thema des Threads:
Ich benutze/kenne UDPSockUtil nicht, aber gibt es da keine Methode SendBuffer?

//Edit

@arbu man: das bezog sich wohl auf die Verwendung von ShortString

Gruß Hawkeye

Union 24. Jun 2006 14:33

Re: RecordtoString
 
Kurze Strings werden in Delphi so gespeichert, wie es im Typ TBuffer zu sehen ist. Das macht Delphi nur, wenn die Länge des Strings vorher (beim Compilieren) bekannt und kleiner oder gleich 255 ist - oder wenn man die Deklaration mit shortstring macht. Strings, die auch Länger werden können (dynamische Strings) werden mit einem Pointer auf die Startadresse der Zeichnkette verwaltet. Wird der String erweitert, wird falls dort nicht genug Speicher zur Verfügung steht, neue Speicher reserviert, der alte Inhalt an die neue Adresse kopiert und die zusätzlichen Informationen angehängt. Dann wird die Adresse in der Variablen ebenfalls geändert.

arbu man 24. Jun 2006 14:53

Re: RecordtoString
 
Zitat:

Zurück zum eigentlichen Thema des Threads:
Ich benutze/kenne UDPSockUtil nicht, aber gibt es da keine Methode SendBuffer?
ja gibt es, in wie fern hilft mir das weiter ?

Chewie 24. Jun 2006 15:02

Re: RecordtoString
 
Zitat:

Zitat von arbu man
ja gibt es, in wie fern hilft mir das weiter ?

Damit wirst du auch records schicken können ;) Zeig doch mal, wie die Methode aufzurufen ist.

arbu man 24. Jun 2006 15:04

Re: RecordtoString
 
Oh man das sehe ich grad auch das erspart mir ja viel arbeit glich mal testen :coder:
(muss dann crossover kabel anschließen, bin aber glich wieder on )

arbu man 24. Jun 2006 15:14

Re: RecordtoString
 
So klappt alles :) Hier ist das ferige Modul:

Das Modul soll die komunikation zwischen Spielen im Netzwerk vereinfachen.
Delphi-Quellcode:
unit uglsn_engine;

{
  G L S N Engine


 Benötigt werden folgende Komponenten:

   # UdpSockUtil - [url]http://www.delphi-forum.de/topic_55339.html[/url]

 Hinweis zur benutzung die Unit WinSock einbinden !

 Copyright 2006 by Björn R. Salgert (bjoern@bsnx.net)
 Internet: glsgames.bsnx.net
}

interface

uses
  SysUtils, Classes, IdBaseComponent, IdComponent, IdIPWatch, UdpSockUtil,
  WinSock, Forms, Dialogs;

const
  ALL = '255.255.255.255';
  GLSN_DEFAULTPORT = 42768;
  GLSN_STR = 0;
  GLSN_POS = 1;

type
  TGLS_IPString = string[18];  { size: 18    4*3+3 }
  TGLS_SString = string[20];   { size: 20          }
  TGLS_LString = string[255];  { size: 255         }
  TGLS_Point = packed record   { size: 24    3*8   }
    X,
    Y,
    Z: Double;
  end;

type
  TGLS_NetSend = packed record { 394 }
    C: Integer;
    K: Integer;
    P: Integer;
    Name: TGLS_SString;
    case Integer of
      0:(
       M1,
       M2,
       M3,
       M4,
       M5: TGLS_SString;
       ML: TGLS_LString;
      );
      1:(
       Pos: TGLS_Point;
       Dir: TGLS_Point;
       Speed: Double;
       Power: Double;
      );
  end;

type
  TGLSN_Exception = Exception;
  TGLS_OnReceiveEvent = procedure(r: TGLS_NetSend;ip: string) of object;
  TGLSN_Engine = class(TDataModule)
    UdpSockUtil: TUdpSockUtil;
    IP: TIdIPWatch;
    procedure UdpSockUtilError(Sender: TObject; Error: Integer);
    procedure UdpSockUtilReceive(Sender: TObject);
    procedure DataModuleCreate(Sender: TObject);
  protected
    FOnRecieveRecord: TGLS_OnReceiveEvent;
  public
    { Public-Deklarationen }
    Eceptions: boolean;
    procedure BroadcastRecord(r: TGLS_NetSend);
    procedure SendRecord(r: TGLS_NetSend; toip: string);
  published
    property OnReceiveRecord: TGLS_OnReceiveEvent read FOnRecieveRecord write
                                                          FOnRecieveRecord;
  end;

var
  GLSN_Engine: TGLSN_Engine;

implementation

{$R *.dfm}

procedure TGLSN_Engine.UdpSockUtilError(Sender: TObject; Error: Integer);
begin
  if Eceptions then
     TGLSN_Exception.Create('GLSN Socket Error: '+inttostr(Error));
end;

procedure TGLSN_Engine.UdpSockUtilReceive(Sender: TObject);
var
  Len: Integer;
  Msg: String;
  vonIP: in_addr;
  buffer: TGLS_NetSend;
begin
  // wieviel ist angekommen?
  Len := UdpSockUtil.ReceiveLength;
  if (Len > 0) then begin // wenn auch was da ist...
    // Nachricht einlesen; in vonIP wird die Absender-IP zurückgegeben
    UdpSockUtil.ReceiveBuf(buffer, sizeof(buffer), vonIP);
    if inet_ntoa(vonIP)<>IP.LocalIP then
    begin
      if Assigned(FOnRecieveRecord) then begin
        FOnRecieveRecord(buffer, inet_ntoa(vonIP));
      end;
    end;
  end;
end;

procedure TGLSN_Engine.DataModuleCreate(Sender: TObject);
begin
  UdpSockUtil.Listen:=true;
end;

procedure TGLSN_Engine.BroadcastRecord(r: TGLS_NetSend);
var
  s: string;
begin
  s:=UdpSockUtil.RemoteHost;
  UdpSockUtil.RemoteHost:=ALL;
  UdpSockUtil.SendBuf(r, sizeof(r));
  UdpSockUtil.RemoteHost:=s;
end;

procedure TGLSN_Engine.SendRecord(r: TGLS_NetSend; toip: string);
var
  s: string;
begin
  s:=UdpSockUtil.RemoteHost;
  UdpSockUtil.RemoteHost:=toip;
  UdpSockUtil.SendBuf(r, sizeof(r));
  UdpSockUtil.RemoteHost:=s;
end;

end.

Khabarakh 24. Jun 2006 15:40

Re: RecordtoString
 
Naja, eine solch speziell zugeschnittene Engine wird wohl niemand außer dir selbst benutzen können ;) . Ein schönes Beispiel für eine generische und einfache Engine wäre z.B. DirectPlay. Wenn du deine noch weiterentwickeln willst, könntest du dich an dieser etwas orientieren.

PS: die Zeile
Delphi-Quellcode:
TGLSN_Exception = Exception;
bringt genau 0 ;) .
Delphi-Quellcode:
TGLSN_Exception = class(Exception);

arbu man 24. Jun 2006 19:22

Re: RecordtoString
 
In erste linie ist die engine für mein Spiel. Aber danke für den Zeile :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 Uhr.

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