回答:
使用するポートが問題ない場合は、ServerSocketコンストラクターに0のポートを指定すると、空いているポートで待機します。
ServerSocket s = new ServerSocket(0);
System.out.println("listening on port: " + s.getLocalPort());
特定のポートのセットを使用したい場合、最も簡単な方法は、1つが機能するまでそれらを反復処理することです。このようなもの:
public ServerSocket create(int[] ports) throws IOException {
for (int port : ports) {
try {
return new ServerSocket(port);
} catch (IOException ex) {
continue; // try next port
}
}
// if the program gets here, no port in the range was found
throw new IOException("no free port found");
}
次のように使用できます:
try {
ServerSocket s = create(new int[] { 3843, 4584, 4843 });
System.out.println("listening on port: " + s.getLocalPort());
} catch (IOException ex) {
System.err.println("no available ports");
}
ssh -D 127.0.0.0:0 ...
かどうかを具体的にテストし、それを拒否します(?いいえ!)。これは本当にイライラします。それらを使用できるようにするには、かなりの数のライブラリ/プログラムにパッチを適用する必要がありました。
new ServerSocket(0)
この点で違いはありません。これに関する最初のリンクには何もありません。2番目のリンクは単に練習不足を示しています。いったん作成しServerSocket
たら、それを使用する必要があります。閉じるのではなく、同じポート番号を再利用してください。これらはすべて時間の無駄であり、タイミングウィンドウの問題に対して脆弱です。
ServerSocketのコンストラクターにポート番号として0を渡すと、ポートが割り当てられます。
Java 1.7以降では、try-with-resourcesを次のように使用できます。
private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
try (
ServerSocket socket = new ServerSocket(0);
) {
return socket.getLocalPort();
}
}
特定のインターフェースで開いているポートを見つける必要がある場合は、ServerSocketのドキュメントで代替コンストラクタを確認してください。
警告:このメソッドによって返されるポート番号を使用するコードはすべて競合状態の影響を受けます。ServerSocketインスタンスを閉じた直後に、別のプロセス/スレッドが同じポートにバインドする場合があります。
SO_REUSEADDR
。そして、競合状態がありますが、それを修正するのは困難です。
ServerSocket
ポート番号が使用されている可能性があるため、後で同じポート番号で別のポート番号を開こうとすると、これが機能しない可能性があります。なぜあなたはServerSocket
それを閉じるのではなく単に実際のものを返さないのかは謎のままです。
ServerSocket
代わりにを受け入れるようにサードパーティのコードを変更することはできませんint
。
Wikipediaによると、「よく知られた」ポートが必要ない場合は、ポート49152
を使用する65535
必要があります。
私の知る限り、ポートが使用されているかどうかを判断する唯一の方法は、ポートを開こうとすることです。
範囲内で使用する必要がある場合:
public int nextFreePort(int from, int to) {
int port = randPort(from, to);
while (true) {
if (isLocalPortFree(port)) {
return port;
} else {
port = ThreadLocalRandom.current().nextInt(from, to);
}
}
}
private boolean isLocalPortFree(int port) {
try {
new ServerSocket(port).close();
return true;
} catch (IOException e) {
return false;
}
}
ServerSockets
で、成功した場合に2つを作成する必要がなく、このコードのタイミングウィンドウの問題の影響を受けません。
Springを使用している場合は、http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/util/SocketUtils.html#findAvailableTcpPort--を試してみてください。
SpringUtils.findAvailableTcpPort()
は他の回答で推奨されているのとまったく同じことをしています:ポートを選択してからを試してくださいnew ServerSocket(port)
。
Eclipse SDKには、必要な処理を実行するSocketUtilクラスが含まれています。gitのソースコードを調べてみてください。
http://java.sun.com/j2se/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29を参照してください
指定されたポートにバインドされたサーバーソケットを作成します。ポート0は、空きポートにソケットを作成します。
サーバーが起動した場合、そのソケットは使用されていません。
編集
何かのようなもの:
ServerSocket s = null ;
try {
s = new ServerSocket( 0 );
} catch( IOException ioe ){
for( int i = START; i < END ; i++ ) try {
s = new ServerSocket( i );
} catch( IOException ioe ){}
}
// At this point if s is null we are helpless
if( s == null ) {
throw new IOException(
Strings.format("Unable to open server in port range(%d-%d)",START,END));
}
new ServerSocket(0)
あなたの代わりにうまくいかない場合はこれがこれです。私の提案を使用してしまう可能性は85%あると思います。
ServerSockets
永久に続け、成功した最後のコードのみを保持します。break
ステートメントが必要です。
を使用して独自のサーバーを作成するServerSocket
場合は、空きポートを選択させるだけです。
ServerSocket serverSocket = new ServerSocket(0);
int port = serverSocket.getLocalPort();
他のサーバーの実装は通常、同様のサポートを備えています。たとえば、明示的に設定しない限り、Jettyは空きポートを選択します。
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
// don't call: connector.setPort(port);
server.addConnector(connector);
server.start();
int port = connector.getLocalPort();
それはあまり役に立たないかもしれませんが、私の(Ubuntu)マシンには、少なくとも一部のアプリが使用/予約するポートが指定された/ etc / servicesファイルがあります。これらはこれらのアプリの標準ポートです。
これらが動作している保証はなく、これらのアプリが使用するデフォルトのポートのみです(したがって、可能であれば使用しないでください)。
500をわずかに超える数のポートが定義されており、半分はUDP、半分はTCPです。
ファイルはIANAの情報を使用して作成されます。IANA割り当てポート番号を参照してください。
Springを使用している場合、Michail Nikolaevによって提供された答えが最も単純で最もきれいなものであり、IMOを支持する必要があります。便宜上、Springframwework SocketUtils .findAvailableTcpPort()メソッドを使用してインラインの例を追加します。
int randomAvailablePort = SocketUtils.findAvailableTcpPort();
それはそれと同じくらい簡単で、1行だけです:)。もちろん、Utilsクラスは他の多くの興味深いメソッドを提供します。ドキュメントを参照することをお勧めします。
'ServerSocket'クラスを使用して、特定のポートが使用中か空きかを識別できます。ServerSocketは、整数(ポート番号)を引数として取り、ポートのサーバーソケットを初期化するコンストラクターを提供します。ServerSocketがIO例外をスローする場合、このポートはすでに使用されていると想定できます。
次のスニペットは、使用可能なすべてのポートを取得するために使用されます。
for (int port = 1; port < 65535; port++) {
try {
ServerSocket socket = new ServerSocket(port);
socket.close();
availablePorts.add(port);
} catch (IOException e) {
}
}
参照リンク。
ポートが別のソフトウェアによって占有されている場合、コードはIOExceptionをスローします