AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Socket-Verbindung herstellen ohne zu blockieren
Thema durchsuchen
Ansicht
Themen-Optionen

Socket-Verbindung herstellen ohne zu blockieren

Ein Thema von Medium · begonnen am 7. Mai 2018 · letzter Beitrag vom 11. Mai 2018
Antwort Antwort
Seite 1 von 3  1 23      
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#1

Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:16
Moin!

Ich muss gerade eine Legacy-Anwendung von uns etwas ändern. Diese kommuniziert via TClientSocket mit einem Server. Da es bei dem Kunden gelegentlich zu Verbindungsstörungen kommt, und sich auch nach längerer Suche für die Ursache keine "richtige" Abhilfe abzeichnet, man aber dennoch weiter arbeiten möchte bis das mal so weit ist, soll mein Programm nun immer mal wieder versuchen sich neu zu verbinden wenn die Verbindung abgebrochen ist.

Dafür habe ich mal spontan einen Timer genommen, der einfach alle 10s prüft ob .Connected = true, und wenn nicht dies setzen. Leider aber friert während des Verbindungsversuchs alles ein, so dass das Programm bei fortwährender Störung alle 10s für 2-3s nicht bedient werden kann. (Man kann sinnvolle Dinge auch ohne die Verbindung tun.)

Kann man den Socket dazu überreden, dies bitteschön im Hintergrund zu tun? Die Events sind alle versorgt, und anhand derer setze ich auch entsprechende Flags. Sodass mir der "Zwischenzustand" nichts ausmachen würde. Ich habe schon lose über einen Thread dafür nachgedacht, aber wenn ich mich nicht täusche kann man Sockets nur in dem jeweiligen Kontext nutzen, in dem sie erstellt bzw. verbunden werden. Und ich habe weder Lust noch Zeit das gesamte Programm so umzustellen, dass ALLE Socket-Zugriffe in einem Thread passieren (mit all dem Signaling usw. was da dran hängen würde).

Gibt's da einen Kniff?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.508 Beiträge
 
Delphi 7 Professional
 
#2

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:28
Nö, was sinnvolles weiß ich nicht, aber wenn der Fehler auftritt, dann in einem Thread alle 10s (oder so) prüfen, ob die Verbindung prinzipiell wiederhergestellt werden kann. Wenn ja, dann im eigentlichen Programmteil die Verbindung wieder aufbauen.
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#3

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:32
Socketzugriffe auf die native Windows Socket API können durchaus auch aus mehreren Threads stattfinden (Beispiel: Indy's Telnet Client schreibt auf den Socket aus einem Thread während ein anderer daraus liest). Bei TClientSocket ist aber leider die gesamte Verarbeitung zusätzlich noch an die Windows Ereignis/Nachrichtenwarteschlange gekoppelt um so die "asynchrone" Verarbeitung zu ermöglichen (Relikt aus den frühen Windows-Zeiten), mit Windowhandles usw. und Dadurch wird das Thema "welcher Thread darf was?" dann doch wieder relevant.

Durch TClientSocket entsteht in der Regel komplexer ("Spaghetti-")Code, der bei einem blockierenden Zugriff auf Sockets wegfällt, was die Wartung langfristig wieder einfacher macht.
Michael Justin
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:35
Hi, ich hab hier zwei Sources entdeckt die das Thema Socket+(multi)Thread aufgreifen, vielleicht ist etwas für Dich dabei?
connecting a server socket with several client sockets und TServerSocket in multithread mode

Mein Tipp wäre erstmal anpingen ob Server überhaupt existiert um Connected = true zu setzen.

edit
für alle dir nur source wollen, hier der aus link 1
Es kann gut möglich sein das in den Links noch Verbesserungen o.ä. erwähnt werden.
Delphi-Quellcode:
unit Server;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Sockets, ServerThread;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  public
    procedure handle(ID, message: String);
  end;

var
  Form1: TForm1;
  threads: Array[1..4] of TServerThread;
  serverSocket: Longint;
  clientSocket: Longint;
  serverAddr: TInetSockAddr;
  opt: Integer = 1;
  addrSize: Longint;
  clientCount: Integer = 0;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  repeat
    serverSocket:= fpSocket(AF_INET, SOCK_STREAM, 0);
    if fpSetSockOpt(serverSocket, SOL_SOCKET, SO_REUSEADDR, @opt, sizeOf(opt)) = SOCKET_ERROR then showMessage('Server : Multi : ' + intToStr(socketError));
    if serverSocket = SOCKET_ERROR then showMessage('Server : Socket : ' + intToStr(socketError));
    serverAddr.sin_family:= AF_INET;
    serverAddr.sin_port:= htons(50000);
    serverAddr.sin_addr.s_addr:= htonl($7F000001);
    if fpBind(serverSocket, @serverAddr, sizeOf(serverAddr)) = SOCKET_ERROR then showMessage('Server : Bind : ' + intToStr(socketError));
    if fpListen(serverSocket, 4) = SOCKET_ERROR then showMessage('Server : Listen : ' + intToStr(socketError));
    showMessage('Waiting for connect from Client...');
    addrSize:= sizeOf(serverAddr);
    clientSocket:= fpaccept(serverSocket, @serverAddr, @addrSize);
    if clientSocket = SOCKET_ERROR then showMessage('Server : Accept : ' + intToStr(socketError)) else clientCount:= clientCount + 1;
    threads[clientCount]:= TServerThread.create(true, clientSocket);
    threads[clientCount].start;
  until clientCount = 4;
end;

procedure TForm1.handle(ID, message: String);
var
  i, toTerminate: Integer;
  MyCriticalSection: TRTLCriticalSection;
begin
  InitCriticalSection(MyCriticalSection);
  EnterCriticalSection(MyCriticalSection);
  try
    for i:= 1 to clientCount do
    begin
      threads.send(ID + ': ' + message);
      if threads.getID = ID then toTerminate:= i;
    end;
    if message = 'ciaothen
    begin
      threads[toTerminate].send('ciao');
      threads[toTerminate].close;
      clientCount:= clientCount - 1;
      for i:= toTerminate to clientCount do threads:= threads[i + 1];
    end;
  finally
    LeaveCriticalSection(MyCriticalSection);
  end;
end;

end.



unit ServerThread;

{$mode objfpc}{$H+}

interface

uses Classes, Dialogs, Sockets, SysUtils;

type
  TServerThread = class(TThread)
  private
    ID: String;
    clientSocket: Longint;
  protected
    procedure execute; override;
  public
    constructor create(createSuspended: Boolean; client: Longint);
    procedure send(msg: String);
    function getID: String;
    procedure close;
  end;

var
  buffer: String[255];
  count: Longint;

implementation

uses Server;

constructor TServerThread.create(createSuspended: Boolean; client: Longint);
begin
  freeOnTerminate:= true;
  inherited create(createSuspended);
  clientSocket:= client;
end;

procedure TServerThread.execute;
begin
  count:= fprecv(clientSocket, @buffer[1], 255, 0);
  if (count <> SOCKET_ERROR) and (count > 0) then
  begin
    setLength(buffer, count);
    ID:= buffer;
  end;
  buffer:= 'Herzlich willkommen im Chat, ' + ID;
  count:= length(buffer);
  if fpsend(clientSocket, @buffer[1], count, 0) = count then
  begin
    repeat
      count:= fprecv(clientSocket, @buffer[1], 255, 0);
      if (count <> SOCKET_ERROR) and (count > 0) then
      begin
        setLength(buffer, count);
        Form1.handle(ID, buffer);
      end;
    until (count = SOCKET_ERROR) or (count = 0);
  end;
end;

procedure TServerThread.send(msg: String);
begin
  fpsend(clientSocket, @msg[1], length(msg), 0);
end;

function TServerThread.getID: String;
begin
  result:= ID;
end;

procedure TServerThread.close;
begin
  closeSocket(clientSocket);
end;

end.



unit Client;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Sockets, ClientThread;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure handle(msg: String);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  thread: TClientThread;
  serverAddr: TInetSockAddr;
  serverSocket: Longint;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  serverSocket:= fpSocket(AF_INET, SOCK_STREAM, 0);
  if serverSocket = SOCKET_ERROR then showMessage('Client : Socket : ' + intToStr(socketError));
  serverAddr.sin_family:= AF_INET;
  serverAddr.sin_port:= htons(50000);
  serverAddr.sin_addr.s_addr:= htonl($7F000001);
  //funktioniert beim zweiten Client nicht, da kein Error, obwohl die Verbindung nicht zustande kommt (fpaccept reagiert nicht)
  if fpconnect(serverSocket, @serverAddr, sizeOf(serverAddr)) = SOCKET_ERROR then showMessage('Client : Connect : ' + intToStr(socketError));
  thread:= TClientThread.create(true, serverSocket);
  thread.start;
  buffer:= Edit1.Text;
  fpsend(serverSocket, @buffer[1], length(buffer), 0);
  Button2.Enabled:= true;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  buffer: String;
begin
  buffer:= Edit2.Text;
  fpsend(serverSocket, @buffer[1], length(buffer), 0);
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
  if length(Edit1.Text) > 0 then Button1.Enabled:= true else Button1.Enabled:= false;
end;

procedure TForm1.handle(msg: String);
begin
  if msg = 'ciaothen closeSocket(serverSocket)
  else Memo1.Lines.Add(msg);
end;

end.



unit ClientThread;

{$mode objfpc}{$H+}

interface

uses Classes, Dialogs, Sockets, SysUtils;

type
  TClientThread = class(TThread)
  private
    serverSocket: Longint;
  protected
    procedure execute; override;
  public
    constructor create(createSuspended: Boolean; server: Longint);
  end;

var
  buffer: String[255];
  count, i: Longint;

implementation

uses Client;

constructor TClientThread.create(createSuspended: Boolean; server: Longint);
begin
  freeOnTerminate:= true;
  inherited create(createSuspended);
  serverSocket:= server;
end;

procedure TClientThread.execute;
begin
  repeat
    count:= fprecv(serverSocket, @buffer[1], 255, 0);
    if count <> SOCKET_ERROR then
    begin
      setLength(buffer, count);
      Form1.handle(buffer);
    end;
  until buffer = 'ciao';
  closeSocket(serverSocket);
end;

end.
hier der aus link 2
Delphi-Quellcode:
program server;

uses
  Forms,
  main in 'main.pas{Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\


 Unit main;

Interface

Uses
  Windows, SysUtils, Messages, Classes, Forms, ScktComp, Controls, StdCtrls,
  Menus, Mask, Spin, ComCtrls, ExtCtrls;

Const
  CM_IncCount = WM_USER + 1;

Type
  TForm1 = Class(TForm)
    ServerSocket: TServerSocket;
    MainMenu: TMainMenu;
    File1: TMenuItem;
    ActiveItem: TMenuItem;
    N1: TMenuItem;
    Exit1: TMenuItem;
    Panel1: TPanel;
    Label1: TLabel;
    CacheEdit: TSpinEdit;
    Label2: TLabel;
    PortEdit: TSpinEdit;
    Label3: TLabel;
    ThreadCount: TEdit;
    Panel2: TPanel;
    ListBox1: TListBox;
    Panel3: TPanel;
    StatusBar1: TStatusBar;
    CharCount: TLabel;
    Procedure ServerSocketGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      Var SocketThread: TServerClientThread);
    Procedure FormCreate(Sender: TObject);
    Procedure FormClose(Sender: TObject; Var Action: TCloseAction);
    Procedure Exit1Click(Sender: TObject);
    Procedure PortEditChange(Sender: TObject);
    Procedure ActiveItemClick(Sender: TObject);
    Procedure ServerSocketThreadEnd(Sender: TObject;
      Thread: TServerClientThread);
    Procedure ServerSocketThreadStart(Sender: TObject;
      Thread: TServerClientThread);
    Procedure CacheEditChange(Sender: TObject);
  protected
    Procedure CMIncCount(Var Msg: TMessage); message CM_IncCount;
  public
  End;

{ TFileServerThread }

  TFileServerThread = Class(TServerClientThread)
  public
    Procedure ClientExecute; override;
  End;

Var
  Form1: TForm1;

Implementation

{$R *.DFM}

{ TFileServerThread }

Procedure TFileServerThread.ClientExecute;
Var
  Data: Array[0..1023] Of char;
  RecText: String;
  SocketStream: TWinSocketStream;
Begin
  While Not Terminated And ClientSocket.Connected Do
  Try
    SocketStream := TWinSocketStream.Create(ClientSocket, 30000);
    Try
      FillChar(Data, SizeOf(Data), 0);
      If SocketStream.Read(Data, SizeOf(Data)) = 0 Then
      Begin
        // If we didn't get any data after xx seconds then close the connection
        ClientSocket.SendText('Timeout on Server'+#13#10);
        //Wait a little time to allow sending of text before disconnect
        sleep(1);
        ClientSocket.Close;
        Terminate;
      End;
      RecText := Data;
      If Length(RecText) > 2 Then
        Delete(RecText, Pos(#13#10, RecText), 2); // Delete 10
      If ClientSocket.Connected Then
      Begin
        ClientSocket.SendText(RecText);
        SendMessage(Form1.Listbox1.Handle, LB_ADDSTRING, 0, Integer(PChar(RecText)));
        PostMessage(Form1.Handle, CM_INCCOUNT, 0, 0);
      End;
    Finally
      SocketStream.Free;
    End;
  Except
    HandleException;
  End;
End;

Procedure TForm1.ServerSocketGetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket;
  Var SocketThread: TServerClientThread);
Begin
  // Create a new thread for connection
  SocketThread := TFileServerThread.Create(False, ClientSocket);
  ClientSocket.SendText('Welcome to Server'+#13#10);
End;

Procedure TForm1.FormCreate(Sender: TObject);
Begin
  CacheEdit.Value := ServerSocket.ThreadCacheSize;
  PortEdit.Value := ServerSocket.Port;
  CharCount.Caption := '0';
  ActiveItemClick(Nil);
End;

Procedure TForm1.FormClose(Sender: TObject; Var Action: TCloseAction);
Begin
  ServerSocket.Close;
End;

Procedure TForm1.CMIncCount(Var Msg: TMessage);
Begin
  CharCount.Caption := IntToStr(StrToInt(CharCount.Caption) + 1);
End;

Procedure TForm1.Exit1Click(Sender: TObject);
Begin
  Close;
End;

Procedure TForm1.PortEditChange(Sender: TObject);
Begin
  ServerSocket.Port := StrToInt(PortEdit.Text);
End;

Procedure TForm1.ActiveItemClick(Sender: TObject);
Begin
  ServerSocket.Active := Not ServerSocket.Active;
  ActiveItem.Checked := ServerSocket.Active;
  If ServerSocket.Active Then
    StatusBar1.SimpleText := 'Active'
  Else
    StatusBar1.SimpleText := 'InActive';
End;

Procedure TForm1.ServerSocketThreadEnd(Sender: TObject;
  Thread: TServerClientThread);
Begin
  ThreadCount.Text := IntToStr(StrToInt(ThreadCount.Text) - 1);
End;

Procedure TForm1.ServerSocketThreadStart(Sender: TObject;
  Thread: TServerClientThread);
Begin
  ThreadCount.Text := IntToStr(StrToInt(ThreadCount.Text) + 1);
End;

Procedure TForm1.CacheEditChange(Sender: TObject);
Begin
  ServerSocket.ThreadCacheSize := CacheEdit.Value;
End;

End.
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 7. Mai 2018 um 19:02 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:46
Die Idee die Verbindung im Thread erstmal anzutesten gefällt mir! Zwar nicht das schönste von der Welt, aber ich brauche in diesem Falle leider das mit dem geringsten Aufwand. (Das Programm ist eh heillos verloren was Wartbarkeit angeht - da muss ich beizeiten mal eine Renovierung anbieten...) Das probiere ich mal!

Ich hatte zwischenzeitlich einfach mal probiert bloß das ".Active := true" in einem Thread zu machen, und dabei ist mir das komplette Programm mit den wildestens Meldungen und manchmal auch gar keinen auf etliche Weisen um die Ohren geflogen . Es hilft vermutlich auch nicht, dass ich in den Event-Handlern reichlich Dinge im UI mache. (Ich vermute mal, dass die dann nämlich auch auf einmal im Thread-Kontext landen.)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 7. Mai 2018, 18:55
[OT?]
Verwendet der Kunde Power-Line oder ähnliches?
Bei mir führt das auch immer mal zu Verbindungsunterbrechungen.
[/OT?]
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
ensaron

Registriert seit: 29. Aug 2008
Ort: 10369 Berlin
63 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 8. Mai 2018, 07:19
Mit der Verlagerung des Sockets in einen Thread bei einer gewachsenen Anwendung hatte ich das Problem der hängenden Programmoberfläche auch mal erfolgreich gelöst. Du musst dann natürlich alle Zugriffe auf den Socket im Thread abhandeln und den Zugriff von außen via TMonitor, CriticalSection oder etwas in der Art absichern.

Die endgültige Lösung war bei mir dann übrigens der Umstieg auf die Overbyte ICS Komponenten, die funktionieren asynchron (und daher ohne Hänger beim Verbindgen etc.). Wenn das für dich eine Option wäre, kann ich ja hier mal ein Beispiel für die Ansteuerung anhängen.
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.800 Beiträge
 
Delphi 12 Athens
 
#8

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 8. Mai 2018, 09:04
Die ICS kann ich auch nur wärmstens empfehlen. Falls Threading angedacht ist, auf jeden Fall dies hier lesen: http://wiki.overbyte.eu/wiki/index.p...MultiThreading

Sherlock
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#9

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 8. Mai 2018, 09:56
@stahli: Ich muss zugeben mich mit den Interna des Kundennetzes nicht eingehend beschäftigt zu haben. Ich bin quasi Netzwerklegastheniker, und die haben eine IT-Abteilung, die gerne möglichst wenig kommuniziert. Ich komme quasi mit meinen Kabeln daher und stöpsel mich an, und wenn nicht geht was gehen sollte sage ich: Hier, kaputt. Hilf. (Und das ist gewünscht so, die lassen keinen anderen an ihr Heiligtum. Was ich auch ein wenig verstehen kann.)

Bzgl. ICS: Danke für den Tipp! Für dieses Projekt im speziellen würde ich solch einen großen Umbau gern tunlichst vermeiden, aber für die Zukunft schau ich mir das definitiv mal an. Kurze Nachfrage: Wo liegt der Vorteil zu den Indys (mit denen ich für neue Projekte auch schon geliebäugelt hatte)?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Socket-Verbindung herstellen ohne zu blockieren

  Alt 8. Mai 2018, 10:00
Ohne allzu fit in dem Thema zu sein, aber kannst du nicht in einen Thread parallel zu der alten TClientSocket-Komponente mit der WinApi einfach nur prüfen, ob der Ziel-Socket da/offen/erreichbar ist und das Ergebnis in den Mainthread synchronisieren und entsprechend reagieren?
https://www.delphi-treff.de/tutorial...ts-mit-winapi/
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:17 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