Einzelnen Beitrag anzeigen

Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#11

Re: Indy10 Kommunikation über UDP mit 8 Bit Codierung

  Alt 16. Jun 2009, 09:39
Hi Alex,

Zitat von AJ_Oldendorf:
Mit SendBuffer haben wir es auch schon probiert und hatten das gleiche Problem mit der Übertragung.
Wäre super, wenn du dir das Beispiel mal anguckst und mir Bescheid gibst.
So, ich habe mir das gerade mal angesehen. Meine Vermutung bezüglich des Encodings stimmt. Allein schon die Tatsache, daß der Compiler Warnungen bezüglich der String-Umwandlung schmeißt, sollte dem Programmierer immer zu denken geben.

Wenn Du in Deinem D2009 Beispiel folgendes änderst, geht es sofort - aber bitte trotzdem unten weiterlesen:
Delphi-Quellcode:
// Senden:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  outMsg: String[2];
begin
  Inc(Counter);
  outMsg[0] := AnsiChar(2);
  outMsg[1] := AnsiChar(Hi(Counter));
  outMsg[2] := AnsiChar(Lo(Counter));

  // IdUDPClient1.Send(outMsg, Indy8BitEncoding);
  IdUDPClient1.Send(outMsg, TEncoding.Unicode); // Delphi Encoding nutzen!
  Label3.Caption := 'Sending: ' + IntToStr(Counter);
end;

...

// Empfangen:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  AData: TBytes; ABinding: TIdSocketHandle);
var
  InData : AnsiString;
  tmpword: Word;
begin
  InData := BytesToString(AData, TEncoding.Unicode); // Delphi Encoding nutzen!

  if (InData = '') or (Length(Indata) < 2) then
  begin
    Memo1.lines.Add('Invalid value');
  end
  else begin
    // Read Word from ByteArray
    tmpword := (Ord(InData[1]) shl 8) or
                Ord(InData[2]);

    Memo1.Lines.Add(IntToStr(tmpword));
  end;

end;
Aber wie gesagt, das so zu nutzen wäre sehr unschön. IdUDPClient1.Send hat als 1. Übergabeparameter einen String. Was glaubst Du also, macht Delphi, wenn Du dort einen Ansi oder ShortString übergibst? Richtig, es konvertiert diesen zu einem UnicodeString.

Der richtige Weg, diese Binärdaten zu übertragen wäre z.B.:
Delphi-Quellcode:
// Senden:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  outData: TBytes;
begin
  Inc(Counter);

  SetLength(outData, 2);
  outData[0] := Hi(Counter);
  outData[1] := Lo(Counter);
  IdUDPClient1.SendBuffer(outData);

  Label3.Caption := 'Sending: ' + IntToStr(Counter);
end;

...

// Empfangen:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  AData: TBytes; ABinding: TIdSocketHandle);
var
  tmpword: Word;
begin
  if Length(AData) < 2 then
  begin
    Memo1.lines.Add('Invalid value');
    // Raise EProgrammerNotFound.Create('nicht da');
  end
  else begin
    // Read Word from ByteArray
    tmpword := (Ord(AData[0]) shl 8) or
                Ord(AData[1]);

    Memo1.Lines.Add(IntToStr(tmpword));
  end;
end;
Und da gibt es dann natürlich auch keine Warnung mehr wegen irgendwelcher String-Conversions. Es werden direkt und unverändert Bytes übertragen.

Das Problem hat nichts, wirklich garnichts mit Indy zu tun. Die Speicherung von Binärdaten in einem String und die daraus folgenden Probleme, kommen seit Delphi 2009 jetzt in vielen Sourcen ans Tageslicht. Ich empfehle dringend mal die Leitfäden bezüglich der D2009 Unicode-Umstellung von Embarcadero, da hier wirklich hilfreiche Infos drin stecken (einfach mal im EDN suchen).

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat