2012-06-06 10 views
5

In meinem Netzwerk befinden sich nur wenige uPNP-Geräte. Ich versuche, M-SEARCH-Anfrage an das Netzwerk zu senden und hoffe, einige Antworten von ihm zu erhalten. Dies ist, was ich versuche:Kann ich IdUDPClient verwenden, um eine M-SEARCH-Anfrage zu senden?

var sIP, sOut: string; 
    iPort: Word; 
    S: TStringBuilder; 
begin 
    S := TStringBuilder.Create; 
    try 
    S.Append('M-SEARCH * HTTP/1.1').AppendLine 
    .Append('HOST: 239.255.255.250:1900').AppendLine 
    .Append('MAN: "ssdp:discover"').AppendLine 
    .Append('MX: 10').AppendLine 
    .Append('ST: ssdp:all').AppendLine; 

    IdUDPClient1.ReceiveTimeout := 3000; 
    IdUDPClient1.Broadcast(S.ToString, 1900, '239.255.255.250'); 
    sOut := IdUDPClient1.ReceiveString(sIP, iPort); 
    Memo1.Lines.Add(sIP); 
    Memo1.Lines.Add(IntToStr(iPort)); 
    Memo1.Lines.Add(sOut); 
    finally 
    S.Free; 
    end; 
end; 

Ich bekomme nichts vom UDP-Client. Ich verwende Wireshark, um den Netzwerkverkehr zu überwachen und es wurde keine Nachricht von meinem Host gesendet.

Irgendwelche Ideen? Vielen Dank.

fand ich die Antwort schließlich:

uses 
    System.SysUtils, IdUDPClient, IdStack; 

var S: TStringBuilder; 
    U: TIdUDPClient; 
    iPeerPort: Word; 
    sPeerIP, sResponse: string; 
begin 
    U := TIdUDPClient.Create(nil); 
    S := TStringBuilder.Create; 
    try 
    S.Append('M-SEARCH * HTTP/1.1').AppendLine 
    .Append('HOST: 239.255.255.250:1900').AppendLine 
    .Append('MAN: "ssdp:discover"').AppendLine 
    .Append('MX: 3').AppendLine 
    .Append('ST: ssdp:all').AppendLine 
    .AppendLine; 

    U.BoundIP := GStack.LocalAddress; 
    U.Send('239.255.255.250', 1900, S.ToString); 

    U.ReceiveTimeout := 1000; 
    repeat 
     sResponse := U.ReceiveString(sPeerIP, iPeerPort); 
     if iPeerPort <> 0 then begin 
     WriteLn(Format('%s:%d', [sPeerIP, iPeerPort])); 
     WriteLn(sResponse); 
     end; 
    until iPeerPort = 0; 
    ReadLn; 
    finally 
    S.Free; 
    U.Free; 
    end; 
end. 

Antwort

6

Anruf AppendLine() zweimal am Ende des Strings Builder. HTTP-Anforderungsheader werden von zwei CRLF-Paaren beendet, Sie hängen jedoch nur ein Paar an, sodass Sie eine unvollständige Anforderung senden.

+0

ich ein neues AppendLine hinzufügen() zum stringbuilder-Objekt, aber ich habe auch keine Antwort erhalten. Ich habe auch nicht bemerkt, dass die Anfrage von meinem Host gesendet wurde, wenn der Verkehr über WireShark überwacht wurde. –

+0

Sind Sie sicher, dass '239.255.255.250' die richtige Broadcast-IP für Ihr LAN ist? Welche lokale IP und welches Subnetz ist dem PC Ihres Kunden zugewiesen? –

+0

Wenn ich an 239.255.255.255 sende, kann ich den von meinem Host gesendeten Verkehr sehen. Aber Sendung an 239.255.255.250, wurde kein Verkehr erkannt. –

3

Schnelle und schmutzige Lösung mit TIudUDPServer (Indy 9).

Löschen Sie die TIudUDPServer-Komponente in das Formular und verwenden Sie den Objektinspektorsatz Bindungen an Ihre lokale IP-Adresse, z. 10.1.0.78:, setzen Sie BroadcastEnabled und Active auf true. Legen Sie ein TMemo und TButton auf dem Formular ab.

die OnClick und UDPRead Events Füllen Sie wie folgt vor:

uses IdSocketHandle; 
... 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
    IdUDPServer1.Send('239.255.255.250', 1900, 'M-SEARCH * HTTP/1.1' + #13#10 + 
    'HOST: 239.255.255.250:1900' + #13#10 + 
    'MAN: "ssdp:discover"'+ #13#10 + 
    'MX: 3'+ #13#10 + 
    'ST: ssdp:all'+ #13#10 + 
    #13#10); 
end; 

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle); 
var 
    data: string; 
begin 

    setlength(data, Adata.Size - AData.Position); //No fragmentation :)   
    AData.ReadBuffer(data[1], length(data)); 

    memo1.Lines.Add('Read: ' + inttostr(AData.Position) + '/' + inttostr(AData.Size) + ' PeerIP: ' + ABinding.PeerIP);  
    memo1.Lines.Add(data); 
end; 

Speichern, Ausführen und Bobs dein Onkel.

0

Für Multicast-M-SEARCH ist das Nachrichtenformat unten definiert. Werte zwischen * * sind Platzhalter für tatsächliche Werte.

M-SEARCH * HTTP/1.1 
HOST: 239.255.255.250:1900 
MAN: "ssdp:discover" 
MX: *seconds to delay response* 
ST: *search target* 
USER-AGENT: *OS/version UPnP/1.1 product/version* 

So müssen Sie ReceiveTimeout zu

U.ReceiveTimeout := 3000; 

es beheben sollte mindestens gleich in Ihrer Anfrage verzögern (MX: 3) 3 sec = 3000 Millisekunden