Entwickler-Ecke

Internet / Netzwerk - Broadcast per TUDPSocket, aber Antwort wird nicht empfangen


Rainer78 - Di 28.07.09 16:20
Titel: Broadcast per TUDPSocket, aber Antwort wird nicht empfangen
Hallo zusammen,

ich bin am Verzweifeln. Ich habe von einem Kollegen ein Projekt übernommen (erstellt mit Delphi 5) und soll es unter Delphi 2005 zum Laufen bekommen. Damals hat der Kollege die FastNet-UDP-Komponente verwendet. Diese funktioniert auch so, wie sie soll. Leider gibt es die Komponenten ja nicht mehr unter 2005 und ich muss auf Indy 10 oder die Internet-Komponenten zugreifen, die Delphi mit liefert.

Das Programm soll einen Broadcast (Inhalt: #0#0#0#F6) an die IP-Adresse 10.49.40.255 schicken. Der PC, auf dem das Progamm gestartet ist, hat die IP 10.49.40.5.

Der Befehl wird abgesetzt und ich erhalte auch eine Antwort von einem weiteren Netzwerkteilnehmer (eine Elektrokarte mit einem LAN-Seriell-Wandler). Dass das Programm die richtigen Daten sendet und die Gegenseite die richtigen Daten sendet kann ich mit einem Netzwerksniffer feststellen. Jedoch wird das Receive-Ereignis nicht aufgerufen wodurch ich dann die Daten, die ich eigentlich empfangen sollte, nicht abarbeiten kann.

Ich habe mal ein Testprogramm geschrieben, um den Dialog zu separieren. Vielleicht findet jemand ja den Fehler, woran es liegen könnte.

Update:
Hatte noch veregssen folgendes zu erwähnen: Ich habe auch schon die Indy 10-Komponenten die bei D2005 dabei sind ausprobiert. Auch die schicken die Daten richtig, aber empfangen wird auch nichts. Die Client-Komponente hat ja noch nicht einmal ein OnReceive bzw. OnDataAvailable Ereignis.

Die Lösung muss nicht auf der TUdpSocket-Komponente beruhen. Indy 10 würde auch gehen... es muss halt alles nur Standard sein.


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:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Sockets;

type
  TForm1 = class(TForm)
    UdpSocket1: TUdpSocket;
    Memo1: TMemo;
    Button1: TButton;
    procedure UdpSocket1Send(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure UdpSocket1Receive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.UdpSocket1Receive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
var
  sTmp : String;
  i : integer;
begin
  sTmp := EmptyStr;
  for i := 0 to Datalen -1 do
    begin
      sTmp := sTmp + '#' + IntToStr(Ord(Buf[i]));
    end;
  Memo1.Lines.Add('Recv: ' + sTmp);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  UdpSocket1.LocalHost := '10.49.40.5';
  UdpSocket1.LocalPort := '30719';
  UdpSocket1.RemoteHost := '10.49.40.255';
  UdpSocket1.RemotePort := '30718';

end;

procedure TForm1.Button1Click(Sender: TObject);
var
  LBuffer : Array [1..4of Byte;
begin
  try
    LBuffer[1]  := $00;
    LBuffer[2]  := $00;
    LBuffer[3]  := $00;
    LBuffer[4]  := $F6;
    UdpSocket1.Active := True;
    UdpSocket1.SendBuf(LBuffer,4);
  finally
  end;
end;

procedure TForm1.UdpSocket1Send(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
var
  sTmp : String;
  i : integer;
begin
  sTmp := EmptyStr;
  for i := 0 to Datalen -1 do
    begin
      sTmp := sTmp + '#' + IntToStr(Ord(Buf[i]));
    end;
  Memo1.Lines.Add('Send: ' + sTmp);
end;

end.


Narses - Di 28.07.09 16:34

Moin und :welcome: im Forum!

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Der Befehl wird abgesetzt und ich erhalte auch eine Antwort von einem weiteren Netzwerkteilnehmer (eine Elektrokarte mit einem LAN-Seriell-Wandler). Dass das Programm die richtigen Daten sendet und die Gegenseite die richtigen Daten sendet kann ich mit einem Netzwerksniffer feststellen. Jedoch wird das Receive-Ereignis nicht aufgerufen wodurch ich dann die Daten, die ich eigentlich empfangen sollte, nicht abarbeiten kann.
Ausgeschlossen, dass die Daten auf dem PC nicht an irgend einer Firewall/etc. hängen bleiben? :?

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe auch schon die Indy 10-Komponenten die bei D2005 dabei sind ausprobiert. Auch die schicken die Daten richtig, aber empfangen wird auch nichts. Die Client-Komponente hat ja noch nicht einmal ein OnReceive bzw. OnDataAvailable Ereignis.
Ja, da die Indy-Kompos threadbasiert mit blocking-socket-calls arbeiten, ist das normal. ;)

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Die Lösung muss nicht auf der TUdpSocket-Komponente beruhen.
Dann schau doch mal, ob du mit dieser Komponente [http://www.delphi-forum.de/topic_TUdpSockUtil+v100++Alternative+zum+IndyUDPClientServer_55339.html] weiter kommst. :nixweiss:

cu
Narses


Rainer78 - Di 28.07.09 16:46

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin und :welcome: im Forum!
Ausgeschlossen, dass die Daten auf dem PC nicht an irgend einer Firewall/etc. hängen bleiben? :?


Also ich abe (Windows Vista-) Firewall deaktiviert, genauso wie den Virenscanner. Ich glaube nicht, dass die Pakete irgendwo hängen bleiben, sonst würde das Snifferprogramm (Analyzer) diese ja nicht anzeigen können.

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Dann schau doch mal, ob du mit dieser Komponente [http://www.delphi-forum.de/topic_TUdpSockUtil+v100++Alternative+zum+IndyUDPClientServer_55339.html] weiter kommst. :nixweiss:


Die Komponente habe ich auch schon ausprobiert. Aber auch die brachte leider keinen Erfolg. :(


Narses - Di 28.07.09 16:52

Moin!

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Also ich abe (Windows Vista-) Firewall deaktiviert, genauso wie den Virenscanner. Ich glaube nicht, dass die Pakete irgendwo hängen bleiben, sonst würde das Snifferprogramm (Analyzer) diese ja nicht anzeigen können.
Hm, Vista also :? zufällig ein XP zum Testen zur Hand? :nixweiss:

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Die Komponente habe ich auch schon ausprobiert. Aber auch die brachte leider keinen Erfolg. :(
Zeich doch bitte mal den Code, noch besser: lade dein Testprojekt als ZIP (ohne die EXE) als Anhang hoch.

cu
Narses


Rainer78 - Di 28.07.09 17:08

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Hm, Vista also :? zufällig ein XP zum Testen zur Hand? :nixweiss:


XP nicht, aber 2000. Und da habe ich genau das gleiche Problme. Lasse ich das mit D5 erzeugt Programm laufen funktioinert es wunderbar. Unter 2000 und Vista.

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Zeich doch bitte mal den Code, noch besser: lade dein Testprojekt als ZIP (ohne die EXE) als Anhang hoch.


Schon geschehen.


Narses - Di 28.07.09 17:25

Moin!

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Zeich doch bitte mal den Code, noch besser: lade dein Testprojekt als ZIP (ohne die EXE) als Anhang hoch.

Schon geschehen.
Ich meinte die Version mit dem TUdpSockUtil; der Delphi-TUDPSocket ist buggy, das der nicht läuft, wundert mich nicht. ;)

cu
Narses


Rainer78 - Di 28.07.09 17:49

Habe es fast gelöst :-)

Es scheint doch mit deiner Komponente zu funktionieren.

Ich bekomme von der Gegenseite 30 Byte geschickt. Wie müßte der Aufruf per ReceiveBuf aussehen ?

Ich hatte folgendes ausprobiert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
...
var
aTmp : Array of Byte;
Len : integer;
RemoteAddr : _in_addr;
begin
Len := UdpSocket1.ReceiveLength;
aTmp := SetLength(Len);
UdpSocket1.ReceiveBuf(aTmp, Len, RemoteAddr);
...

Aber in aTmp bekomme ich die Daten nicht rein :-(


Narses - Di 28.07.09 18:07

Moin!

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Es scheint doch mit deiner Komponente zu funktionieren.
:D

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Ich bekomme von der Gegenseite 30 Byte geschickt. Wie müßte der Aufruf per ReceiveBuf aussehen ?
Probier das mal so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.UdpSockUtil1Receive(Sender: TObject);
  var
    aTmp: Array of Byte;
    Len, i: Integer;
    RemoteAddr: in_addr;
begin
  Len := UdpSockUtil1.ReceiveLength;
  Memo1.Lines.Add(IntToStr(Len)+' Bytes');
  SetLength(aTmp,Len);
  UdpSockUtil1.ReceiveBuf(Pointer(aTmp)^, Len, RemoteAddr);
  for i := 0 to Len-1 do
    Memo1.Lines.Add(IntToStr(aTmp[i])+' '+Char(aTmp[i]));
end;
cu
Narses


Rainer78 - Mi 29.07.09 08:33

Vielen Dank !!!

Jetzt funktioniert es.

Schönen Tag noch !!

CU

Rainer


jaenicke - Mi 29.07.09 08:57

Wobei was UDP angeht es vielleicht auch noch wichtig ist zu wissen, dass die Pakete auch einfach mal nicht ankommen könnten, wenn es einen Übertragungsfehler gibt. Das ist explizit so vorgesehen, dass man davon auch nichts weiter mitbekommt, da UDP z.B. für Sprachübertragungen z.B. gedacht ist, bei denen es unwichtig ist, ob jedes einzelne Paket ankommt.

Ich weiß gerade nicht inwieweit Paketverlust oder andere Reihenfolge von Paketen bei TUdpSockUtil bereits berücksichtigt / korrigiert werden.


Narses - Mi 29.07.09 11:15

Moin!

user profile iconRainer78 hat folgendes geschrieben Zum zitierten Posting springen:
Vielen Dank !!!

Jetzt funktioniert es.
You´re welcome. ;)

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ich weiß gerade nicht inwieweit Paketverlust oder andere Reihenfolge von Paketen bei TUdpSockUtil bereits berücksichtigt / korrigiert werden.
Gar nicht, ist ein reiner API-Wrapper.

cu
Narses