Frage

Ich weiß, ich habe viel zu fragen ... aber als neuer delphi Entwickler ich über all diese Fragen fallen weiter:)

Dieses befasst sich mit TCP-Kommunikation indy 10. Verwendung Kommunikation effizienter zu machen, habe ich einen Client Betriebsanforderung als ein einziges Byte-Code (in den meisten Szenarien, die von anderen Datenbytes natürlich gefolgt, aber in diesem Fall nur ein einziges Byte). Das Problem ist, dass

var Bytes : TBytes;
...
SetLength (Bytes, 1);
Bytes [0] := OpCode;
FConnection.IOHandler.Write (Bytes, 1);
ErrorCode := Connection.IOHandler.ReadByte;

nicht, dass Byte sendet sofort (zumindest die Server ausführen Handler nicht aufgerufen wird). Wenn ich die ‚1‘ auf eine ‚9‘ zum Beispiel ändern funktioniert alles einwandfrei. Ich nahm an, dass Indy puffert das abgehende Bytes und versuchte Schreib Pufferung mit

deaktivieren
FConnection.IOHandler.WriteBufferClose;

, aber es hat nicht geholfen. Wie kann ich ein einzelnes Byte und stellen Sie sicher, dass diese die sofort gesendet wird? Und - ich fügen Sie eine weitere kleine Frage hier - was ist der beste Weg, um eine ganze Zahl mit indy zu schicken? Leider kann ich nicht funktionieren wie Writeinteger im IOHandler von TIdTCPServer finden ... und

WriteLn (IntToStr (SomeIntVal))

scheint mir nicht sehr effizient. Macht es einen Unterschied, ob ich mehrere Schreibbefehle in einer Reihe verwenden oder Sachen packen zusammen in einem Byte-Array und senden, dass einmal?

Vielen Dank für alle Antworten!

EDIT: Ich habe einen Hinweis, dass ich Indy 10 bin mit, da es große Veränderungen scheinen in Bezug auf die zu lesende und Verfahren schreiben

.
War es hilfreich?

Lösung

Write-Pufferung ist standardmäßig deaktiviert. Sie können Schreibpuffer überprüfen, um zu sehen, ob es in Ihrem Code aktiv ist, indem Sie die fConnection.IOHandler.WriteBufferingActive Eigenschaft zu testen.

Was die beste Möglichkeit, eine ganze Zahl zu senden ... ‚es hängt‘ auf dem Protokoll und Gesamtzielen. Insbesondere verwendet FConnection.IOHandler.Write (), wie es Methoden überlastet sind fast jede Art von Daten zu schreiben, einschließlich einer ganzen Zahl.

Entnommen IdIOHandler:

// Optimal Extra Methods
//
// These methods are based on the core methods. While they can be
// overridden, they are so simple that it is rare a more optimal method can
// be implemented. Because of this they are not overrideable.
//
//
// Write Methods
//
// Only the ones that have a hope of being better optimized in descendants
// have been marked virtual
procedure Write(const AOut: string; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure WriteLn(const AEncoding: TIdEncoding = enDefault); overload;
procedure WriteLn(const AOut: string; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure WriteLnRFC(const AOut: string = ''; const AEncoding: TIdEncoding = enDefault); virtual;
procedure Write(AValue: TStrings; AWriteLinesCount: Boolean = False; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure Write(AValue: Byte); overload;
procedure Write(AValue: Char; const AEncoding: TIdEncoding = enDefault); overload;
procedure Write(AValue: LongWord; AConvert: Boolean = True); overload;
procedure Write(AValue: LongInt; AConvert: Boolean = True); overload;
procedure Write(AValue: SmallInt; AConvert: Boolean = True); overload;
procedure Write(AValue: Int64; AConvert: Boolean = True); overload;
procedure Write(AStream: TStream; ASize: Int64 = 0; AWriteByteCount: Boolean = False); overload; virtual;

Eine andere Frage, die Sie hatten, war „Macht es einen Unterschied, ob ich mehrere Schreibbefehle in einer Reihe verwenden oder Sachen packen zusammen in einem Byte-Array und das einmal senden?“ Für die Mehrzahl der Fälle macht es ja einen Unterschied. Für hochbeanspruchte Server werden Sie mehr in bekommen haben, wie Bytes hin und her geschickt, aber auf dieser Ebene sollten Sie abstrahieren Sie sendet in eine separate Protokolltyp-Klasse, die die Daten baut sie in einem gesendet und sendet werden Burst und eine Empfangsprotokoll hat, das eine Reihe von Daten und verarbeitet sie als komplette Einheit anstatt zu brechen Dinge empfängt bis zu Senden / Empfangen einen ganze Zahl, Zeichen, Byte-Array, etc ..

Als grobes kurzes Beispiel:

TmyCommand = class(TmyProtocol)
private
  fCommand:Integer;
  fParameter:String;
  fDestinationID:String;
  fSourceID:String;
  fWhatever:Integer;
public
  property Command:Integer read fCommand write fCommand;
  ...

  function Serialize;
  procedure Deserialize(Packet:String);
end;

function TmyCommand.Serialize:String;
begin
  //you'll need to delimit these to break them apart on the other side
  result := AddItem(Command) + 
            AddItem(Parameter) + 
            AddItem(DestinationID) + 
            AddItem(SourceID) + 
            AddItem(Whatever);
end; 
procedure TMyCommand.Deserialize(Packet:String);
begin
   Command := StrToInt(StripOutItem(Packet));
   Parameter := StripOutItem(Packet);
   DesintationID := StripOutItem(Packet); 
   SourceID := StripOutItem(Packet);
   Whatever := StrToInt(StripOutItem(Packet));
end;

Dann senden Sie diese über:

  FConnection.IOHandler.Write(myCommand.Serialize());

Auf der anderen Seite, um die Daten über Indy empfängt und dann

  myCommand.Deserialize(ReceivedData);

Andere Tipps

Ich bin nicht vertraut mit Indy, aber Sie könnten um seine API für eine TCP_NODELAY Option aussehen soll (man könnte die Indy-Source-Tree für so etwas grep wollen -. Groß- und Kleinschreibung für „Verzögerung“ sollte es tun)

Edit: Rob Kennedy wies darauf hin, dass die Eigenschaft I beziehen ist TIdIOHandlerSocket.UseNagle - dank

Das Problem liegt in der Natur von TCP inhärent. TCP übernimmt keine Garantie Datenlieferung in der gleichen Reihenfolge wie sie emittiert wurde, aber tut nicht Grenzen Garantie Nachricht. Mit anderen Worten, das Betriebssystem der Quelle, des Ziels und alle Router auf dem Weg frei Pakete von der Verbindung koaleszieren oder sich nach Belieben fragmentieren. Sie müssen als ein Strom bei einer TCP-Übertragung sehen, nicht als eine Reihe von einzelnen Paketen. So haben Sie einen Mechanismus einzuführen, mit denen Sie entweder die einzelnen Nachrichten begrenzen (durch ein magisches Byte, zum Beispiel, die Sie müssen entkommen, wenn es auch in Ihrer Nachrichtendaten auftreten können), oder Sie können die Länge der folgenden Meldung senden zuerst, dann die eigentliche Nachricht.

Ich habe immer verwendet UDP mit einem naiven ACK / Neuübertragungsschemas gekoppelt, wenn ich brauchte, um Nachrichten zu senden, wo die Nachricht Grenze war wichtig, wie der Fall ist. Vielleicht möchten, dass berücksichtigen. UDP ist viel besser für Befehlsnachrichten geeignet.

Klingt wie Sie Ihre Puffer zu spülen haben. Versuchen Sie folgendes:

TIdTCPConnection.FlushWriteBuffer;

Wenn Sie nicht über einen Schreibpuffer möchten, verwenden Sie diese:

TIdTCPConnection.CancelWriteBuffer;

Nach der Hilfe dieser erste ruft ClearWriteBuffer, um den Puffer zu löschen und ruft dann CloseWriteBuffer.

Der besten Weg, eine ganze Zahl (mit Indy 10) senden TIdIOHandler.Write mit (nach Indy 10 Hilfe Schreiben ist überlastet verschiedene Arten von Daten zu handhaben, einschließlich ganzen Zahlen)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top