DatagramSocket无法从UdpClient接收数据。

3
我正在制作一个Win RT应用程序,它连接到桌面应用程序并开始使用UDP和TCP进行通信。
我已经成功地实现了TCP通信,我可以从Win RT发送数据到桌面,也可以从桌面发送数据到Win RT。在Win RT上使用StreamSocket,在桌面上使用TcpListener。
我还成功地将Udp数据从Win RT发送到桌面,没有任何问题。但是我无法接收来自桌面发送到Win RT的数据。我使用以下代码,我没有发现任何问题,但一定有什么问题。
    var g = new DatagramSocket();
    g.MessageReceived += g_MessageReceived;
    g.BindEndpointAsync(new HostName("127.0.0.1"), "6700");
    .
    .
    .
    void g_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
    { // <- break point here.

    }

断点永远无法停止代码,这意味着它永远不会收到消息。 我只能想到IBuffer,因为在我的StreamSocket上,我应该通过reader.GetBuffers()获取字节而不是reader.GetBytes()。然而,在Win RT上需要考虑的事情就是这个。因为在Tcp上,我只发送字节并且在Win RT中获取缓冲区,所以DatagramSocket也应该是一样的。

  • reader = DataReader

谢谢大家。


这篇文章可能会有所帮助。http://msdn.microsoft.com/zh-cn/library/windows/apps/Hh780593.aspx - Adrian Salazar
1个回答

5
我不熟悉新的DatagramSocket类,但通常绑定到127.0.0.1意味着你只会接收发送到回环适配器的消息。由于您的数据包来自另一台主机,它们应该在网卡上而不是回环适配器上接收到。
编辑:从查看您正在使用的DatagramSocket API文档来看,您可以使用BindServiceNameAsync()方法而不是BindEndpointAsync()方法,以便在所有适配器上绑定到指定端口,这与我下面的System.Net.Sockets API示例行为相同。因此,在您的示例中,您将拥有:
g.BindServiceNameAsync("6700");

当然,您还需要确保桌面主机的防火墙设置允许其在指定端口上监听传入的UDP数据包。
请尝试以下代码:
    using System.Net;
    using System.Net.Sockets;

    public class UdpState
    {
        public UdpClient client;
        public IPEndPoint ep;
    }

    ...

    private void btnStartListener_Click(object sender, EventArgs e)
    {
        UdpState state = new UdpState();
        //This specifies that the UdpClient should listen on EVERY adapter
        //on the specified port, not just on one adapter.
        state.ep = new IPEndPoint(IPAddress.Any, 31337);
        //This will call bind() using the above IP endpoint information. 
        state.client = new UdpClient(state.ep);
        //This starts waiting for an incoming datagram and returns immediately.
        state.client.BeginReceive(new AsyncCallback(bytesReceived), state);
    }

    private void bytesReceived(IAsyncResult async)
    {
        UdpState state = async.AsyncState as UdpState;
        if (state != null)
        {
            IPEndPoint ep = state.ep;
            string msg = ASCIIEncoding.ASCII.GetString(state.client.EndReceive(async, ref ep));
            //either close the client or call BeginReceive to wait for next datagram here.
        }
    }

请注意在上述代码中,您应该使用与发送字符串时相同的编码方式。当我编写测试应用程序时,我发送了ASCII字符串。如果您正发送Unicode,请改用UnicodeEncoding.Unicode而不是ASCIIEncoding.ASCII
如果所有这些方法都不起作用,您可能需要使用像Wireshark这样的数据包捕获工具来确保从RT主机发送的UDP数据包实际上已经到达桌面主机。

你有机会尝试将 BindEndpointAsync 更改为 BindServiceNameAsync 吗?我没有 Windows 8 开发工具,所以无法自己尝试,但从 MSDN 文档中看来,你的代码应该可以使用这个更改。此外,如果你需要在 Win 8 之前的 Windows 版本上运行代码,我提供的代码应该可以工作。我已经测试过了。 - reirab
我还没有尝试过你的代码,但我确实尝试了BindServiceNameAsync,根据MSDN的说法,它等同于在IPAddress.Any上进行绑定,但什么也没发生。我猜这可能是编码、最大字节大小或某些属性的差异所致。 - Peyman
而且,127.0.0.1 不应该是问题,因为我正在使用相同 IP 的模拟器进行测试。但是,为了确保,我已经这样做了,但它没有起作用 :( - Peyman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接