Autor Beitrag
Schwedenbitter
Hält's aus hier
Beiträge: 15

Windows 10

BeitragVerfasst: Mi 07.12.16 13:03 
Hallo,

zunächst möchte ich mich bei Narses für dessen super Anleitungen bzgl. Netzwerkkommunikation bedanken. Ich nutze eine aufgebohrte Version auf einem Linux-Server. Leider nutzen die Sockets von Borland die VCL, so dass ich eine VM mit Windows brauche.
Ein Ausweg sind die Indys. Ich versuche gerade nach 10 Jahren wieder in das Thema zu kommen. Leider scheitere ich daran, dass es mir mit den Indys irgendwie nicht gelingen will, AnsiStrings (für Header und Daten) "verlustfrei" zu versenden.

Natürlich habe ich die Suche benutzt und habe diverse Dinge gefunden. Leider klappt aber folgender Code bei mir nicht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
Procedure TMainForm.Button1Click(Sender: TObject);
Var
  Command      : TCmdSeq;
Begin
  Command:= TCmdSeq.Create($4711);            // Kommandosequenz erzeugen
  Try
    Memo1.Lines.Append(Dump(Command.Frames));    // Kommando-String anzeigen
    Client.Socket.WriteLn(Command.Frames,      // Kommando senden
      IdGlobal.IndyTextEncoding_8Bit);        // 8 bit = AnsiString ?
  Finally
    Command.Free;                      // Objekt wieder freigeben
  End;
End;

Procedure TMainForm.ServerExecute(AContext: TIdContext);
Var
  BinMessage    : AnsiString;
Begin
  If AContext.Connection.Socket.Readable Then    // Es gibt Daten zum Lesen
  Begin
    BinMessage:= AContext.Connection.Socket.ReadLn(
      IdGlobal.IndyTextEncoding_8Bit);          // 8 bit = AnsiString ?
    Memo1.Lines.Append(
      IntToStr(Length(BinMessage)) + ' Zeichen gelesen: ' + #13#10 +
      Dump(BinMessage));                // Daten in hex-Darstellung
  End;
End;

TCmdSeq arbeitet intern natürlich mit AnsiString und liefert auch das richtige Ergebnis vor dem versenden. Wenn ich das durchlaufen lasse, erhalte ich folgende Ausgabe:
ausblenden Quelltext
1:
2:
3:
04 00 00 80 01 00 11 47 
8 Zeichen gelesen: 
04 00 00 3F 01 00 11 47


Wie schaffe ich es, dass die Indys meinen AnsiString auch als solches behandeln und nicht "kaputt" machen?

Gruß, Alex
Schwedenbitter Threadstarter
Hält's aus hier
Beiträge: 15

Windows 10

BeitragVerfasst: Do 08.12.16 13:33 
Ich habe natürlich weiter getestet und dachte schon, ich hätte es geschafft. Leider aber wohl doch nicht. Mit folgendem Code sah es ganz gut aus:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
//      IdGlobal.IndyTextEncoding_Default;    = $3F
//      IdGlobal.IndyTextEncoding_8Bit);      = $3F
//      IdGlobal.IndyTextEncoding_ASCII);    = $3F
//      IdGlobal.IndyTextEncoding_UTF16LE);    = zusätzliches Zeichen
//      IdGlobal.IndyTextEncoding_OSDefault);  = $80 klappt nicht ab $0A
//      IdGlobal.IndyTextEncoding_UTF16BE);    = $80 klappt nicht ab $0A
//      IdGlobal.IndyTextEncoding_UTF7);      = $80 klappt nicht ab $0A
//      IdGlobal.IndyTextEncoding_UTF8);      = $80 klappt nicht ab $0A

Var
  T:Word = 0;

Procedure TMainForm.Button1Click(Sender: TObject);
Var
  Command      : TCmdSeq;
Begin
  Command:= TCmdSeq.Create($4711);            // Kommandosequenz erzeugen
  Try
    Command.Token:= T; Inc(T);// ==> zum Testen den Token ändern
    Memo1.Lines.Append(
      IntToStr(Length(Command.Frames)) + ' Zeichen geschrieben: ' + #13#10 +
      Dump(Command.Frames));              // Daten in hex-Darstellung
    Client.Socket.DefStringEncoding:= IdGlobal.IndyTextEncoding_UTF7;
    Client.Socket.WriteLn(Command.Frames);      // Kommando senden
  Finally
    Command.Free;                      // Kommandosequenz freigeben
  End;
End;

Procedure TMainForm.ServerExecute(AContext: TIdContext);
Var
  BinMessage    : AnsiString;
Begin
  If AContext.Connection.Socket.Readable Then    // Es gibt Daten zum Lesen
  Begin
    AContext.Connection.Socket.DefStringEncoding:= Client.Socket.DefStringEncoding;
    BinMessage:= AContext.Connection.Socket.ReadLn;
    Memo1.Lines.Append(
      IntToStr(Length(BinMessage)) + ' Zeichen gelesen: ' + #13#10 +
      Dump(BinMessage) + #13#10 +           // Daten in hex-Darstellung
      '-----------------------------');
  End;
End;

Abfänglich sehen die Ausgaben vielversprechend aus. Aber ab einem Zeichen mit $0A ist das ganze aber nicht mehr brauchbar:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
8 Zeichen geschrieben: 
04 00 00 80 01 00 09 00 
8 Zeichen gelesen: 
04 00 00 80 01 00 09 00 
-----------------------------
8 Zeichen geschrieben: 
04 00 00 80 01 00 0A 00 
6 Zeichen gelesen: 
04 00 00 80 01 00 
-----------------------------
8 Zeichen geschrieben: 
04 00 00 80 01 00 0B 00 
1 Zeichen gelesen: 
00 
-----------------------------
8 Zeichen geschrieben: 
04 00 00 80 01 00 0C 00 
8 Zeichen gelesen: 
04 00 00 80 01 00 0B 00 
-----------------------------
8 Zeichen geschrieben: 
04 00 00 80 01 00 0D 00 
8 Zeichen gelesen: 
04 00 00 80 01 00 0C 00
usw...


Offenbar gibt es keine Möglichkeit, Strings in binärer Form mit den Indys zu versenden.

Ich habe dann mein Glück damit versucht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
Procedure TMainForm.Button1Click(Sender: TObject);
Var
  ...
  Buffer      : TIdBytes;
Begin
  ...
    Buffer:= RawToBytes(Command.Frames, Length(Command.Frames));
    Client.Socket.Write(Buffer);
  ...;
End;
Procedure TMainForm.ServerExecute(AContext: TIdContext);
Var
  Buffer      : TIdBytes;
  ByteCount    : Integer;
  ...
Begin
  ...
    ByteCount:= ??? // <== Wie komme ich da heran?
    AContext.Connection.Socket.ReadBytes(Buffer, ByteCount);
    BytesToRaw(Buffer, BinMessage, ByteCount);
    ...
End;

Allerdings weiß ich nicht, wie ich an die genau Anzahl der übertragenen Bytes gelange. Kann mir dabei jemand helfen?

Gruß, Alex
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1164
Erhaltene Danke: 183

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 08.12.16 18:04 
In der Unit IdGlobal hast du verschiedene Methoden um ein TIdBytes nach was auch immer zu konvertieren, wenn es dir darum geht.

_________________
„Nicht für das Leben, sondern für die Schule lernen wir.“ „Kürze die lange Rede, damit sie nicht verdächtig wirke!“
(Lucius Annaeus Seneca : 1 - 65 n. Chr)