Einzelnen Beitrag anzeigen

nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

[Indy 10, TCP] Client->Server Kommunikationsprobleme

  Alt 12. Jan 2009, 15:32
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.

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 ...

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 ...
  Mit Zitat antworten Zitat