2012-06-06 20 views
5

W mojej sieci jest kilka urządzeń z interfejsem użytkownika. Próbuję wysłać żądanie M-SEARCH do sieci i mam nadzieję, że otrzymam od niego odpowiedzi. Oto, co próbuję:Czy mogę użyć IdudPClient do wysłania zapytania M-SEARCH?

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; 

Nic nie otrzymuję od klienta UDP. Używam Wireshark do monitorowania ruchu w sieci i żadna wiadomość nie została wysłana z mojego hosta.

Wszelkie pomysły? Dziękuję Ci.

Znalazłem odpowiedź na koniec:

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. 

Odpowiedz

6

połączenia AppendLine() dwukrotnie na końcu konstruktora ciąg. Nagłówki żądania HTTP są kończone przez dwie pary CRLF, ale dodajesz tylko jedną parę, więc wysyłasz niekompletne żądanie.

+0

dodać nowy AppendLine() do obiektu typu Stringbuilder, ale nie otrzymałem żadnej odpowiedzi. Nie zauważyłem też, że żądanie wysyłane jest z mojego hosta podczas monitorowania ruchu przez WireShark. –

+0

Czy jesteś pewien, że '239.255.255.250' to poprawny adres IP twojej sieci LAN? Jaki lokalny adres IP i podsieć jest przypisany do komputera twojego klienta? –

+0

Jeśli nadaję do 239.255.255.255, widzę ruch wysyłany z mojego hosta. Ale transmisja do 239.255.255.250, nie wykryto ruchu. –

3

Szybkie i Brudne rozwiązanie za pomocą TIdUDPServer (Indy 9).

Upuść komponent TIdUDPServer na formularzu i za pomocą Inspektora obiektów ustaw powiązania z lokalnym adresem IP, np. 10.1.0.78:0, ustaw BroadcastEnabled i Active na true. Upuść TMemo i TButton na formularzu.

wypełnić onclick i UDPRead Imprezy następująco:

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; 

Zapisz, biegać i Boba wuja.

0

W przypadku multiemisji M-SEARCH format wiadomości jest zdefiniowany poniżej. Wartości między * * są symbolami zastępczymi dla rzeczywistych wartości.

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* 

Więc trzeba naprawić ReceiveTimeout do

U.ReceiveTimeout := 3000; 

powinna być co najmniej równa opóźnienia w swoim wniosku (MX: 3) 3 s = 3000 milisekund