Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi [Indy 10, TCP] Client->Server Kommunikationsprobleme (https://www.delphipraxis.net/127381-%5Bindy-10-tcp%5D-client-server-kommunikationsprobleme.html)

nuclearping 12. Jan 2009 14:32


[Indy 10, TCP] Client->Server Kommunikationsprobleme
 
Hallo liebe Community!

Erstmal noch Happy New Year nachträglich!

Ich bastel grad privat an einem kleinen Spielchen, was ich später auch gern hier + OpenSource veröffentlichen möchte. Allerdings würde ich vorher gern noch den Multiplayer-Part hinbekommen. Single-Player + AI funktioniert schon soweit. :wink:

Das ist das erste mal, dass ich konkret was mit Indy mache. Hab daher im Internet rumgeschaut und rumprobiert und ein Netzwerk-Prototyp funktionierte sogar schon recht gut mit einem Kumpel übers Internet.
Allerdings hab ich die Kommunikation per String-Commands aufgebaut, so wie ich es auch aus den Tutorials und Demos erstmals gesehen und übernommen hab.
Um Traffic zu sparen und damit Latenzzeiten gering zu halten, wollte ich diese Kommunikation nun auf Byte- und Integer-Ebene abstrahieren und statt mit .IOHandler.WriteLn und .ReadLn mit .Write und .ReadBytes arbeiten.

Das Problemchen dabei ist, dass die Kommunikation Server->Client klappt. Allerdings streikt jetzt die Kommunikation Client->Server total, obwohl es quasi der gleiche Code ist. Und ich verstehe nicht warum. Ich such schon seit Tagen im Netz, probiere hier und da rum. Aber es klappt nicht so, wie ich's will ... :gruebel:

Typ TBroadcastType:
Delphi-Quellcode:
TBroadcastType = record
   Command,
   Value1,
   Value2,
   Value3: Integer;
end;
PBroadcastType = ^TBroadcastType;
1) Server -> Client:
Delphi-Quellcode:
procedure TXYZObserver.BroadcastServerCommand(Command, Value1, Value2,
   Value3: Integer);
var
   cList: TList;
   Count: Integer;
   StrCommand: String;
   EventItem: TBroadcastType;
   Buffer: TIdBytes;
begin
   EventItem := PrepareBroadcastEvent(Command, Value1, Value2, Value3);
   StrCommand := BuildServerCommandString (Command, Value1, Value2, Value3);
   AddLog ('>> Sending Command to Clients: ' + StrCommand);

   Buffer := RawToBytes(EventItem, sizeof (TBroadcastType));
   cList := FXYZServer.Contexts.LockList;
   try
      for Count := 0 to cList.Count -1 do
         with TIdContext(cList[Count]) do
            Connection.IOHandler.Write (Buffer);
   finally
      FXYZServer.Contexts.UnlockList;
   end;
end;
2) Client -> Server:
Delphi-Quellcode:
procedure TXYZObserver.BroadcastEventToServer(Command, Value1, Value2,
   Value3: Integer);
var
   StrCommand: String;
   EventItem: TBroadcastType;
   Buffer: TIdBytes;
begin
   // ** Client sending Event to Server
   EventItem := PrepareBroadcastEvent(Command, Value1, Value2, Value3);
   StrCommand := BuildServerCommandString(Command, Value1, Value2, Value3);
   AddLog ('>> Sending Command to Server: ' + StrCommand);
   Buffer := RawToBytes(EventItem, sizeof (TBroadcastType));
// {*1}   FXYZClient.IOHandler.WriteLn('TEST');
   FXYZClient.IOHandler.Write(Buffer);
end;
3) Server OnExecute Event:
Delphi-Quellcode:
procedure TXYZObserver.ProcessServerIncomingEvent(AContext: TIdContext);
var
   EventItem: PBroadcastType;
   Buffer: TIdBytes;
begin
{*2}   if not AContext.Connection.IOHandler.Connected then
      Exit;

   New (EventItem);
   AContext.Connection.IOHandler.ReadBytes(Buffer, SizeOf (TBroadcastType));
   BytesToRaw (Buffer, EventItem^, SizeOf (TBroadcastType));
   ReceiveIncomingEvent(EventItem);
end;
4) Process Client Incoming:
Delphi-Quellcode:
procedure TXYZObserver.ProcessClientIncomingEvent;
var
   SvStrInput: String;
   EventItem: PBroadcastType;
   Buffer: TIdBytes;
begin
   if not FXYZClient.Connected then
      Exit;
   if FXYZClient.IOHandler.InputBuffer.Size <= 0 then
      Exit;
   New (EventItem);
   FXYZClient.IOHandler.ReadBytes(Buffer, SizeOf (TBroadcastType));
   BytesToRaw (Buffer, EventItem^, SizeOf (TBroadcastType));
   ReceiveIncomingEvent(EventItem);
end;
Die Punkte 1) + 4) funktionieren zusammen so wie gedacht. Allerdings 2) + 3) überhaupt nicht.

Was passiert ist folgendes:
- Ich hab bei {*2} einen Breakpoint gesetzt.

- Wenn ich beim Server einen Event auslöse (Bewege von X nach Y), kommt das beim Client an, wird empfangen, verarbeitet, in die Que gehauen und abgearbeitet. So wie gewollt und gedacht.

- Wenn ich beim Client allerdings den gleichen Event auslöse, kommt nichts beim Server an. Der Breakpoint wird nicht ausgelöst. Erst wenn ich im Client "spamme", wird er ausgelöst. Allerdings kommt dann bei ReadBytes (und BytesToRaw) nur Müll raus. Nicht das, was ich gesendet hab.

- Wenn ich allerdings die Kommentare vor {*1} entferne (und dafür Write auskommentiere), wird sofort bei der ersten Aktion vom Klient, der Breakpoint beim Server ausgelöst.

- Beide Programme laufen auf dem selben Rechner.

Also zusammengefasst: Arbeite ich mit .ReadLn und .WriteLn, funktioniert alles so wie gedacht. Ersetze ich das durch einen Record (4 Integers), funktioniert nur noch Server->Client, aber nicht mehr Client->Server, obwohl es vom Prinzip der selbe Code ist.

Kann mir jemand sagen warum? Wahrscheinlich ists nur ne Kleinigkeit, aber ich seh da nix ... :gruebel:

nuclearping 13. Jan 2009 09:16

Re: [Indy 10, TCP] Client->Server Kommunikationsprobleme
 
Ich bin mal so frei, zu pushen.

nuclearping 14. Jan 2009 02:28

Re: [Indy 10, TCP] Client->Server Kommunikationsprobleme
 
Kann mir da keiner helfen? :pale:

DataCool 15. Jan 2009 23:19

Re: [Indy 10, TCP] Client->Server Kommunikationsprobleme
 
Hi,

wie ist die Kommunikation vom Client zum Server aufgebaut ?
Ist die Client-Connection(IdTcpClient) in einem seperaten Thread ?

Greetz Data

nuclearping 16. Jan 2009 07:12

Re: [Indy 10, TCP] Client->Server Kommunikationsprobleme
 
Ich hab rausgefunden, dass Write vom Client zum Server kein OnExecute-Event auslöst.
Wenn man durch WriteLn stept, macht er daraus Write (ABuffer + EOL (= $D$A)). Ergo: Wenn ich meinen Buffer um 2 Bytes erweitere und dort $D$A hinterlege, funktionierts und beim Server kommt das an, was gesendet wurde.

Holpert aber immernoch ein bisschen. Jedoch bin ich erstmal einen Schritt weiter. :D


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:46 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