【问题标题】:Java Datagram Sockets not receiving packetsJava 数据报套接字不接收数据包
【发布时间】:2010-12-03 01:02:22
【问题描述】:

我正在尝试使用 Java 数据报在服务器和客户端之间创建数据包流。问题是,虽然我收到了正在发送数据包的确认信息,但它们在到达我设置的客户端侦听器之前都丢失了。我现在有它,所以 5 秒后会超时,每次运行时都会发生这种情况。

class DGServer extends Thread
{
    private DatagramSocket server;

    public DGServer() throws IOException
    {
        server = new DatagramSocket();
    }

    public void run()
    {
        try
        {
            server.connect(App.Local, 4200);
            System.out.println("Server starting...");

            int i = 0;

            while (server.isConnected() && (i < 256))
            {
                byte[] buffer = new byte[1];
                buffer[0] = (byte) ++i;
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length, App.Local, 4200);
                System.out.println("Sedning " + i + " to client...");

                server.send(packet);

                Thread.sleep(500);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        System.out.println("Server Finished!");

        if (! server.isClosed())
            server.close();
    }

}

class DGClient extends Thread
{
    private DatagramSocket client;

    public DGClient() throws SocketException
    {
        client = new DatagramSocket();
    }

    public void run()
    {
        try
        {
            client.connect(App.Local, 4200);
            client.setSoTimeout(5000);
            System.out.println("Client starting...");

            int i = 0;

            while (client.isConnected() && (i < 256))
            {
                byte[] buffer = new byte[1];
                DatagramPacket packet;
                packet = new DatagramPacket(buffer, 1, App.Local, 4200);
                //System.out.println("Sedning " + i + " to server...");

                client.receive(packet);

                buffer = packet.getData();          
                System.out.println("Client Received:\t" + packet.getData()[0]);

                Thread.sleep(500);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        System.out.println("Client Finished!");

        if (! client.isClosed())
            client.close();
    }

}

您可以选择略读第二节课。它们大体相同,只是将 server.send 替换为 client.receive。此外,这个类并不是为了真正做任何重要的事情而设计的。所以,很多代码(比如异常处理)都写得很简单。

有什么办法可以防止数据包丢失吗?我在我的电脑上转发了端口(没关系,我使用的是我的本地主机,如果你想知道它是 App.Local)。

另外,附带问题。我最初将它设置为一个单独的类,编码为发送一个数据包,然后转身接收一个数据包。但它抛出了一个异常,因为“ICMP 端口无法访问”。有谁知道为什么会这样?

【问题讨论】:

  • 你怎么知道他们迷路了?您是否尝试过设置像 wireshark 这样的数据包跟踪器来查看它们的去向?

标签: java sockets packet datagram loss


【解决方案1】:

好的,首先,我认为您正在同时测试服务器和客户端,所以您不知道哪个失败了。

您应该使用 netcat (nc) 或 wireshark 来测试客户端

使用netcat,可以运行以下命令

nc -l -u -p 4200 -vv

这将告诉 netcat 在端口 (-p 4200) 上的 udp (-u) 上侦听 (-l) 并且非常详细 (-vv)

这样您就可以检查您的客户端是否可以连接到任何东西。

您可以使用相同的程序来检查您的服务器是否可以接收来自已知工作程序的连接

nc -u [target ip] 4200

There is a netcat cheatsheet here

您还可以检查 netcat 到 netcat 以诊断它是否纯粹是网络问题。可能防火墙/NAT 配置不正确

【讨论】:

    【解决方案2】:

    为什么服务器和客户端都进行连接? 一方不应该发送数据吗?

    类似:

    DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4200); socket.send(packet);

    【讨论】:

      【解决方案3】:

      在我看来,有一些数据包过滤器/防火墙干扰了您正在使用的端口上的客户端和服务器之间的 UDP 流量。可能是简单的数据包过滤,也可能是 NAT(除非您采取特殊步骤,否则它会干扰 UDP 流量),也可能是一些意外的网络配置错误。

      但它引发了异常,因为“ICMP 端口无法访问”。有谁知道为什么会这样?

      IMO,这是包过滤的更多证据。

      (但是,您应该在尝试发送数据报时收到此响应,这也有点出乎意料。我只是希望根本没有响应,并且对 UDP 请求的任何 ICMP 响应都已被丢弃在操作系统的地板上。但是,我可能错了......

      现在,如果您使用的是常规流套接字;例如TCP/IP,这种行为是可以理解的。)

      【讨论】:

      • 它是在以下上下文中;客户端.发送(数据包);客户端.receive(数据包);它实际上在接收线上。
      • 也许正在发生的事情是操作系统正在将意外的 ICMP 流量传送回 UDP 数据报套接字,并且当您执行 receive 时它会变成异常。无论哪种方式,这都是数据包过滤的证据。
      【解决方案4】:

      您没有将发送套接字绑定到特定的端口号,因此如果连接,客户端将无法发送给它。我怀疑你也有同样的问题,即客户端套接字未绑定到端口 4200。这可以解释一切。

      我会在发送时摆脱连接并使用显式端口号,在回复时使用传入端口号。

      【讨论】:

        【解决方案5】:

        我相信您知道 UDP 是一种有损协议,并且您已经允许这样做。你仍然应该期望得到一些数据包。

        我建议您通过在同一主机和不同主机上使用客户端和服务器来测试您的程序是否工作,避免任何防火墙。如果这可行,则说明您有网络配置问题。

        【讨论】:

          【解决方案6】:

          如果您在同一台机器上同时运行它们,这将永远无法工作,因为您将两者(服务器和客户端)连接到同一个端口。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-23
            • 2011-09-09
            • 1970-01-01
            • 2011-10-04
            • 2020-09-24
            相关资源
            最近更新 更多