There are few uPNP devices in my network. I am trying to send M-SEARCH request to the network and hope receiving some responses from it. This is what I am trying:
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;
I receive nothing from the UDP client. I use Wireshark to monitor network traffic and no message was send out from my host.
Any ideas? Thank you.
I found the answer finally:
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.
Call AppendLine()
twice at the end of the string builder. HTTP request headers are terminated by two CRLF pairs, but you are only appending one pair, so you are sending an incomplete request.
Quick and Dirty solution using TIdUDPServer (Indy 9).
Drop the TIdUDPServer component on the form, and using Object Inspector set Bindings to your local IP eg. 10.1.0.78:0, set BroadcastEnabled and Active to true. Drop a TMemo and TButton on the form.
Complete the OnClick and UDPRead Events as follows:
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;
Save, Run and Bob's your uncle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With