java - 如何在线程中继续尝试获取 Java DatagramSocket?

标签 java multithreading udp

我正在开发 Java UDP 应用程序。应用程序中有一个线程,其唯一的工作是监听特定端口上的服务器。

我编写应用程序时错误地假设我正在监听的服务器将始终处于运行状态;然而,这是一个错误的假设。

如果我的应用程序在服务器运行后启动,则一切正常。如果我的应用程序在服务器启动之前启动,或者在我的应用程序运行时重新启动服务器,我的应用程序就会中断。

MainClass.java

public class MainClass {
    public static void main(String[] args){
        ListeningClass myListeningClass = new ListeningClass();
        Thread listenerThread = new Thread(myListeningClass);
        listenerThread.setName("My Listening Thread");
        listenerThread.start();
    }
}

ListeningClass.java

public class ListeningClass implements Runnable {
    private volatile boolean run = true;
    private byte[] receiveBuffer;
    private int receiveBufferSize;
    private DatagramSocket myDatagramSocket;
    private DatagramPacket myDatagramPacket;

    @Override
    public void run(){
        try {
            myDatagramSocket = new DatagramSocket(null);
            InetSocketAddress myInetSocketAddress = new InetSocketAddress(15347);
            myDatagramSocket.bind(myInetSocketAddress);

            receiveBuffer = new byte[2047];
            myDatagramPacket = new DatagramPacket(receiveBuffer, 2047);

            while(run){
                myDatagramSocket.receive(myDatagramPacket);
                byte[] data = myDatagramPacket.getData();
                receiveBufferSize = myDatagramPacket.getLength();
                // process the data received here
            }
        } catch (SocketException se){
            // do stuff
        } catch (IOException ioe){
            // do stuff
        }
    }

    public boolean isRun(){
        return run;
    }

    public void setRun(boolean run){
        this.run = run;
    }
}

就像我说的,如果我的应用程序在服务器运行后启动,一切都会完美运行,正如预期的那样。但是,如果我的应用程序在服务器运行之前启动,那么什么都不起作用。显然,这是因为线程尝试打开连接一次,如果失败,则不会再尝试。

我将 DatagramSocket 打开代码移至 while block 内,但这并不漂亮。我收到一堆“端口已绑定(bind)”错误。

那么,我该如何重建它才能正常工作?

最佳答案

这并不是一个真正的并发问题。您只需要检查接收时抛出的异常并进行适当的处​​理。在这种情况下,请重新绑定(bind)套接字。请参阅docs用于接收

例如:

...
while(run) {
    try {
        myDatagramSocket.receive(myDatagramPacket);
        byte[] data = myDatagramPacket.getData();
        receiveBufferSize = myDatagramPacket.getLength();
        // process the data received here
    } catch (IOException ioe) {
        // Perhaps use PortUnreachableException but not guaranteed
        rebind(myDatagramSocket, myInetSocketAddress);
    }
}

private void rebind(DatagramSocket s, InetSocketAddress addr) {
    s.bind(addr);
}

我认为这应该足够了。关键是,只有当您的接收表明服务器存在 I/O 问题时,您才需要重新绑定(bind)。如果您将绑定(bind)放在循环中,那么您将为每个接收进行绑定(bind) - 这在您的快乐路径情况下是可以的。

关于java - 如何在线程中继续尝试获取 Java DatagramSocket?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35065839/

相关文章:

android - Cordova 插件阻塞线程

asp.net - 构建基于 Internet 的 p2p 文本、音频、视频聊天应用程序

java - 在 Java 中解析 Youtube API 日期

c# - 使用 C# 在 Windows 8 上获取当前线程 ID

java - Apache Tiles 替代品

java - Repaint 和 Mouselister Java

C# UDP - 可以告诉 Windows 在一定时间后丢弃数据包吗?

php - Node.js UDP 流

java - 此 jdbc 资源是否已关闭?

java - hadoop:无法运行 mapreduce 作业