我在windows 8 metro程序中实现SSDP发现有问题。下面是代码:
public async Task SearchForDevices()
{
var socket = new DatagramSocket();
socket.MessageReceived += async (sender, args) =>
{
Debug.WriteLine("Received data" + DateTime.Now);
DataReader reader = args.GetDataReader();
uint count = reader.UnconsumedBufferLength;
string data = reader.ReadString(count);
Debug.WriteLine(data);
var response = new Dictionary<string, string>();
foreach (
string x in
data.Split(new[] {"rn", "n"}, StringSplitOptions.None))
{
if (x.Contains(":"))
{
string[] strings = x.Split(':');
response.Add(strings[0].ToLower(), x.Remove(0, strings[0].Length + 1));
}
}
Device device = await GetXml(response);
Debug.WriteLine("Device found");
if (DeviceFound != null)
DeviceFound(this, new DeviceFoundEventArgs(device));
};
await socket.BindEndpointAsync(null, "");
HostName hostName = new HostName("239.255.255.250");
socket.JoinMulticastGroup(hostName);
string message = "M-SEARCH * HTTP/1.1rn" +
"HOST: " + hostName.DisplayName + ":1900rn" +
"ST: upnp:rootdevicern" +
"MAN: "ssdp:discover"rn" +
"MX: 3rnrn";
DateTime start = DateTime.Now;
TimeSpan interval = new TimeSpan(0, 0, 30);
Debug.WriteLine(start);
IOutputStream stream = await socket.GetOutputStreamAsync(hostName, "1900");
var writer = new DataWriter(stream) { UnicodeEncoding = UnicodeEncoding.Utf8 };
writer.WriteString(message);
await writer.StoreAsync();
await Task.Delay(1500);
}
这个代码一点也不可靠。大约50%的情况下,它找不到连接的设备,而其他发现可以找到。但有时它是有效的。
我的网络嗅探器(SmartSniff)有时甚至不能捕获它的SSDP请求,即使我已经多次发出呼叫。
我不认为这是一个异步问题,因为它偶尔工作。请帮帮我!谢谢!
尝试将本地端点绑定到分配给您希望发送UDP多播请求的本地网络适配器的IP地址。
事实上,你没有看到传出UDP数据包与你的数据包嗅探器让我相信,请求是在一个不同的网络接口上发送的,从一个你正在捕获。我假设您有多个网络接口(例如以太网和WLAN)。当处理多播时,你必须确保你的请求在所有网络接口上发出,以物理地到达所有连接的网络。
我认为你必须在插座上强制SocketOptionName.ReuseAddress
。我无法解释为什么我这么认为,你显然没有像@Joern那样试图使用端口1900作为本地端点。但这是我能看到的唯一区别,他的情况仍然适用:很可能有另一个UPnP控制点已经在你的Windows机器上运行。试试在Windows管理工具中禁用UPnP服务,看看你的代码是否运行得更可靠。
或者尝试重写以@Joern方式建立的UDP套接字。我不是c#专家,但当某些api允许你以多种不同的方式做同样的事情时,我总是很怀疑。
如果我正确地猜测await Task.Delay(1500);
意味着您允许任务在完成前运行1.5秒,那么您有一个有趣的问题原因。
你看,"MX: 3"在M-SEARCH中的意思是"回复随机延迟,最多3秒"。假设您只等待1.5秒,那么您将丢失大约50%的响应;-)