1

我正在尝试使用 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 端口无法访问”。有谁知道为什么会这样?

4

6 回答 6

5

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

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

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

nc -l -u -p 4200 -vv

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

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

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

nc -u [target ip] 4200

这里有一个 netcat 备忘单

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

于 2010-12-03T01:28:25.130 回答
1

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

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

于 2010-12-03T06:26:33.127 回答
1

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

就像是 :


DatagramSocket socket = new DatagramSocket();

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

于 2010-12-03T01:25:36.237 回答
1

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

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

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

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

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

于 2010-12-03T01:26:46.027 回答
0

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

于 2012-05-08T22:15:36.817 回答
0

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

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

于 2010-12-03T07:46:33.683 回答