繁体   English   中英

无法通过互联网接收数据报

[英]Unable to receive datagram over the internet

我有一个UDP客户端向我的UDP服务器发送数据包。

当我使用服务器的IP地址或使用路由器的公用IP地址时,成功发送和接收数据包

// Works
Constants.SERVER_IP_ADDRESS

// Works
Constants.PUBLIC_IP_ADDRESS;

但是,即使设置了转发功能,通过Internet发送时也无法接收任何数据包。

知道为什么吗? 谢谢。

UdpClient

public class UdpClient {

    private String mServerAddress = Constants.PUBLIC_IP_ADDRESS;
    private int mServerPort = Constants.PORT;
    private static final int MAX_TRIES = 5;

    public void sendDatagramPacket(){

        // Cannot network on Main UI thread
        new AsyncTask(){
            @Override
            protected Object doInBackground(Object[] objects) {

                System.out.println("sendDatagramPacket");

                // Create a socket
                DatagramSocket socket = null;
                try{socket = new DatagramSocket();}
                catch (SocketException e){e.printStackTrace();}

                // Create a datagram
                byte[] bytesToSend = new byte[3];
                bytesToSend[0] = (byte) 255;
                bytesToSend[1] = (byte) 255;
                bytesToSend[2] = (byte) 255;

                InetAddress serverInetAddress = null;
                try{serverInetAddress = InetAddress.getByName(mServerAddress);}
                catch (UnknownHostException e) {e.printStackTrace();}

                DatagramPacket datagramPacket = new DatagramPacket(
                        bytesToSend, bytesToSend.length, serverInetAddress, mServerPort);

                // Send packet; packets may be lost, so we have to keep trying
                int tries = 0;
                while(tries < MAX_TRIES) {
                    try{socket.send(datagramPacket);}
                    catch (NullPointerException e){e.printStackTrace();}
                    catch (IOException e){e.printStackTrace();}
                    tries++;
                }

                try{socket.close();}
                catch (NullPointerException e){e.printStackTrace();}

                return null;
            }
        }.execute();
    }
}

UdpServer

public class UdpServer {

    private int mHostPort = Constants.MAC_PORT;

    // Defines max receive-buffer size; maximum possible for UDP is ~64,000
    private static final int MAX_BUFFER_SIZE = 256;

    public void listenForPacket(){

        System.out.println("listenForPacket");

        new Thread(){
            @Override
            public void run(){

                // Get the socket to the receiving port
                DatagramSocket socket = null;
                try { socket = new DatagramSocket(mHostPort);}
                catch (SocketException e){e.printStackTrace();}

                // Create receive-buffer and receive-packet
                byte[] receiveBuffer = new byte[MAX_BUFFER_SIZE];
                DatagramPacket datagramPacket = new DatagramPacket(receiveBuffer,MAX_BUFFER_SIZE);

                // Pause thread here listening for packet
                try{
                    socket.receive(datagramPacket);
                    System.out.println("Datagram received successfully");
                }
                catch (IOException e){e.printStackTrace();}



                try{socket.close();}
                catch (NullPointerException e){e.printStackTrace();}
            }
        }.start();
    }
}

这个答案不能直接解决您的问题,但可以间接解决。 (您的不良异常处理可能隐藏了其他问题...)

您在处理异常的方式上遇到系统性问题。 例如:

    DatagramSocket socket = null;
    try { socket = new DatagramSocket(mHostPort);}
    catch (SocketException e){e.printStackTrace();}

如果构造函数抛出异常会怎样?

答:打印堆栈跟踪,然后继续进行,好像没有发生任何不良情况一样。

除了坏事发生的事。 的确,如果构造失败,你没有一个DatagramSocket ,那么剩下的代码不可能工作。 但是你“恢复了”。

在许多地方都重复这种模式。 确实,您最终得到了捕获不正确“恢复”代码直接导致的NPE的代码。

这是正确的方法:

public void run() {
    try (DatagramSocket socket = new DatagramSocket(mHostPort)) { 

        // Get the socket to the receiving port
        DatagramSocket socket = new DatagramSocket(mHostPort);

        // Create receive-buffer and receive-packet
        byte[] receiveBuffer = new byte[MAX_BUFFER_SIZE];
        DatagramPacket datagramPacket = 
             new DatagramPacket(receiveBuffer,MAX_BUFFER_SIZE);

        // Pause thread here listening for packet
        socket.receive(datagramPacket);
        System.out.println("Datagram received successfully");
    }
    catch (IOException | RuntimeException e) {
        e.printStackTrace();
    }
}

注意事项:

  • 除了更正确(我声称)之外,此代码实际上比您的版本更简单 错误情况更少,并且(我声称)这些讨厌的NPE的来源已被消除。
  • 异常处理不会尝试恢复。 如果发生异常,线程将立即结束...
  • 请注意使用try-with-resources来确保套接字始终处于关闭状态。
  • 捕获RuntimeException可能是不必要的...有关NPE,请参见上文。
  • run()方法中处理异常的另一种方法是使用默认的异常处理程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM