确定UDP主机是否可达
本文关键字:是否 主机 UDP 确定 | 更新日期: 2023-09-27 18:03:02
我有一个metro应用程序使用UDP通过wifi与设备交谈。但是,当我断开设备与网络的连接或在设备断开连接的情况下启动应用程序时,什么也没有发生。ConnectAsync不会抛出异常,应用也不会抛出异常,应用运行起来就像没什么问题一样。我不能ping到另一端但如果我给它一个格式化的字符串它会响应。该设备目前连接到一个可以上网的路由器,但我最终计划使用一个不能上网的路由器。我从来没有用UDP做过任何事情,所以我在这里不知所措。
这是一个UDP侦听器/写入器的实现(取自Pete Bright at 10rem.net)
class Network
{
private DatagramSocket _socket;
public bool IsConnected { get; set; }
public bool recieved;
public string ret;
public Network()
{
IsConnected = false;
_socket = new DatagramSocket();
_socket.MessageReceived += OnSocketMessageReceived;
}
public async void Connect(HostName remoteHostName, string remoteServiceNameOrPort)
{
try
{
await _socket.ConnectAsync(remoteHostName, remoteServiceNameOrPort);
}
catch (Exception e)
{
var msg = new MessageDialog(e.ToString());
msg.ShowAsync();
}
IsConnected = true;
}
private void OnSocketMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
var reader = args.GetDataReader();
var count = reader.UnconsumedBufferLength;
var data = reader.ReadString(count);
ret = data.Trim();
recieved = true;
}
DataWriter _writer =null;
public async void SendMessage(string message)
{
if (String.IsNullOrEmpty(message)) return;
if (_writer == null)
{
var stream = _socket.OutputStream;
_writer = new DataWriter(stream);
}
_writer.WriteString(message);
await _writer.StoreAsync();
}
}
UDP套接字是"无连接"的,因此协议不知道服务器和客户端是否连接。要知道连接是否仍然处于"活动"状态,您必须实现自己的连接检测。
我可能建议阅读beej的套接字指南。这是一本很好的读物,非常有趣。http://beej.us/guide/bgnet/
如前所述,没有像tcp/ip中的sync/ack等那样的概念来来回通信并确保某些东西存在。
客户端既没有连接也没有断开,只有真正的侦听或发送。因此,您需要实现从客户端接收超时。
UDP有一些有趣的笑话,因为你发送数据,基本上只是把它扔到太空。接收数据包的顺序也无关紧要,否则您也只能在这里实现自己的方案。你需要做的是试着到达设备。如果你关心,那么你可以每X秒执行一次。
如下所述:如何测试远程UDP端口
(跟着我,下面有一个更好的方法,但想提供多种方法)
<>之前你可以使用UdpClient,在底层套接字上设置一个接收超时,与远程服务器/端口建立连接,发送一些小消息(byte[] !)并调用Receive。如果端口是关闭的,你会得到一个异常,说连接被强制关闭(SocketExceptionErrorCode 10054 = WSAECONNRESET)…这意味着端口未打开。之前然而,我认为更好的方法是在协议id或客户端每X秒发送的一些特定数据上达成一致。如果收到,则更新客户端已连接表,否则认为它们已断开,直到客户端发送带有协议id over的数据包。
一个很好的系列,你可以很容易地适应c#:http://gafferongames.com/networking-for-game-programmers/virtual-connection-over-udp/
我相信你上面的代码也可以重构,只发送()到一个地址,而不是连接,因为真的没有真正的连接。
帮助那些偶然发现这一点的人:显然我的google-fu相当弱。这展示了如何为TCP和UDP套接字设置超时。默认行为是永远不会超时(这与我所看到的一致)。
编辑:它不工作。即使超时500毫秒,我仍然看到相同的行为"没有抛出异常"。