2012-06-06 29 views
5

我的网络中很少有uPNP设备。我正在尝试向网络发送M-SEARCH请求,并希望收到一些响应。这是我想要的:我可以使用IdUDPClient发送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. 

回答

6

呼叫AppendLine()两次字符串生成器的结尾。 HTTP请求标头由两个CRLF对终止,但您只追加一对,因此您发送的请求不完整。

+0

我添加一个新AppendLine ()到stringbuilder对象,但我也没有收到任何回应。当通过WireShark监控流量时,我也没有注意到从我的主机发出的请求。 –

+0

你确定'239.255.255.250'是你局域网的正确广播IP吗?本地IP和子网分配给客户的PC? –

+0

如果我广播到239.255.255.255,我可以看到从我的主机发出的流量。但广播到239.255.255.250,没有检测到流量。 –

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; 

保存,运行和鲍勃是你的叔叔。

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毫秒

相关问题