Java 尝试绑定到端口,如果失败,请选择其他端口

Java 尝试绑定到端口,如果失败,请选择其他端口,java,Java,我正在写一个点对点应用程序。我有一个应用程序绑定到的默认端口。 但如果失败,我希望我的应用程序绑定到另一个开放端口 我有一个解决办法,但我认为这不是一个很好的办法 我在想这样的事情: package de.oompf.netwrk; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.Inet

我正在写一个点对点应用程序。我有一个应用程序绑定到的默认端口。 但如果失败,我希望我的应用程序绑定到另一个开放端口

我有一个解决办法,但我认为这不是一个很好的办法

我在想这样的事情:

    package de.oompf.netwrk;

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    import java.net.SocketException;

    class Server implements Runnable {
        private final Thread serverThread;
        private final DatagramSocket socket;

        Server() throws SocketException {
            serverThread = new Thread(this, "Server Thread");
            socket = new DatagramSocket(null);
            socket.setSoTimeout(2400);

            for(int port : Configuration.getPortList()) {
                if(!socket.isBound()) {
                    try {
                        socket.bind(new InetSocketAddress(port));
                        break;
                    } catch(SocketException e) {
                    }
                } else {
                    break;
                }
            }

            if(!socket.isBound()) {
                socket.bind(new InetSocketAddress(0));
            }
        }

        void start() {
            serverThread.start();
        }

        void stop() {
            serverThread.interrupt();
            socket.close();
        }

        @Override
        public void run() {
            DatagramPacket p = new DatagramPacket(new byte[4096], 4096);
            while(!serverThread.isInterrupted()) {
                try {
                    socket.receive(p);
                } catch (IOException e) {
                    if(socket.isClosed()) {
                        break;
                    }
                }
            }
        }

    }
但是,在第一次尝试将套接字绑定到端口失败后,套接字将关闭

那么在Java中最优雅的方法是什么呢?

试试这个

       for(int port : Configuration.getPortList()) {
            if(!socket.isBound()) {
                try {
                    socket.bind(new InetSocketAddress(port));
                    break;
                } catch(Exception e) {
                }
            } 
        }


    }

解决方案是为需要测试的每个端口创建一个新的套接字。您的问题是您已经声明了套接字字段final。因此,解决方案是创建一个局部变量来存储套接字,直到您确定已成功绑定套接字或将套接字的创建委托给另一个方法为止

DatagramSocket socket = null;
for (int port : Configuration.getPortList()) {
    try {
        socket = new DatagramSocket(port);
        break;
    } catch (SocketException ignored) {
        continue;
    }
}
if (socket == null) {
    socket = new DatagramSocket(0); 
}
this.socket = socket;


不久前我也做过同样的工作,我通过创建一个PortScanning方法解决了这个问题,该方法返回下一个可用端口的值。然后,我将该端口传递给我的连接线程,因为循环总是被中断或中断;不管绑定成功与否。不,它不是。有两个“break”语句。第一个只有在绑定成功后才能执行。这里有一个类似的问题,有许多有用的答案:为什么不绑定到端口0,让操作系统为YouTunks选择正确的端口!第一个解决方案是我所说的“我有一个解决方案”。但到目前为止,第二种方法是最好的方法。正如我所说的,这是行不通的。绑定失败时,套接字将关闭。
Server() throws SocketException {
    serverThread = new Thread(this, "Server Thread");
    socket = getBoundSocket();
    socket.setSoTimeout(2400);
}

private static DatagramSocket getBoundSocket() throws SocketException {
    for (int port : Configuration.getPortList()) {
        try {
            return new DatagramSocket(port);
        } catch (SocketException ignored) {
            continue;
        }
    }
    return new DatagramSocket(0); 
}