我的网络中的uPNP设备很少。我正在尝试向网络发送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;
我从UDP客户端没有收到任何信息。我使用Wireshark来监控网络流量,并且没有消息从我的主机发出。
有什么想法吗?谢谢。
我终于找到了答案:
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.
答案 0 :(得分:6)
在字符串构建器的末尾调用AppendLine()
两次。 HTTP请求标头由两个CRLF对终止,但您只附加一对,因此您发送的请求不完整。
答案 1 :(得分:3)
使用TIdUDPServer(Indy 9)快速而肮脏的解决方案。
将TIdUDPServer组件放在表单上,然后使用Object Inspector将Bindings设置为本地IP,例如。 10.1.0.78:0,将BroadcastEnabled和Active设置为true。在表单上删除TMemo和TButton。
完成OnClick和UDPRead事件,如下所示:
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;
保存,跑步,鲍勃是你的叔叔。
答案 2 :(得分:0)
对于多播M-SEARCH,消息格式定义如下。 * *之间的值是实际值的占位符。
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*
所以你需要将ReceiveTimeout修复为
U.ReceiveTimeout := 3000;
它应该至少等于您的请求延迟(MX:3)3秒= 3000毫秒