确定UDP主机是否可访问?

时间:2013-03-07 16:15:48

标签: c# windows-store-apps

我有一个地铁应用程序使用UDP通过wifi与设备通话。但是,当我断开设备与网络的连接或在设备断开连接时启动应用程序时,没有任何反应。 ConnectAsync不会抛出异常,应用程序不会抛出异常,应用程序运行就像没有错。 我不能ping另一端但是如果我给它一个格式化的字符串它会响应。该设备目前连接到具有互联网接入的路由器,但我最终计划使用没有互联网接入的路由器。我从未对UDP做过任何事情,所以我在这里不知所措。

这是UDP侦听器/写入器的实现(取自Perem 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();
        }            

    }

3 个答案:

答案 0 :(得分:1)

UDP套接字是“无连接”,因此协议不知道服务器和客户端是否已连接。要知道连接是否仍处于“活动状态”,您必须实现自己的连接检测。

我可能会建议阅读beej的插座指南。这是一个很好的阅读和非常有趣: http://beej.us/guide/bgnet/

答案 1 :(得分:1)

正如所说的那样,没有像tcp / ip中有sync / ack等概念来回传递并确保存在某些东西。

客户端既不连接也不断开连接,只是真正收听或发送。 所以说你需要从客户端实现接收超时。

有一些有趣的笑话与UDP,因为你发送数据,只是基本上把它扔进太空。接收数据包的顺序也无关紧要,或者您也无法在此处实施自己的方案。

您需要做的是实际尝试访问设备。如果你关心,那么你可以每隔X秒做一次。

如此处所述:How to test a remote UDP Port

(请跟我一起,这是一个更好的方法,但希望提供多种方法)

You can use UdpClient, set a receive timeout on the underlying socket, 
make a connection to that remote server/port, Send some small message
 (byte[] !) and call Receive.

IF the port is closed you get an exception saying that the connection 
was forcibly closed (SocketException with
 ErrorCode 10054 = WSAECONNRESET)... which means the port is NOT open.

但是 - 我认为更好的方法是实际上就协议ID或客户端每X秒发送一些特定数据达成一致。如果收到,则更新“客户端连接”表,否则请将其断开,直到客户端发送协议ID超过的数据包。

伟大系列就可以轻松适应c#: http://gafferongames.com/networking-for-game-programmers/virtual-connection-over-udp/

我相信上面的代码也可以重构为只发送()到一个地址而不是连接,因为实际上没有真正的连接。

答案 2 :(得分:0)

帮助那些偶然发现的人:显然我的google-fu非常弱。 This显示了如何为TCP和UDP套接字设置超时。默认行为是永不超时(这与我所看到的一致)。

编辑:它不起作用。即使超时为500毫秒,我仍然会看到“无异常抛出”的相同行为。