Sementara pertanyaan ini adalah tentang bagaimana mengetahui apakah port tertentu sudah digunakan, Anda mungkin telah mendarat di sini mencoba menemukan cara untuk mendapatkan nomor port gratis, yang stackoverflow.com/questions/2675362/… (dengan tautan ke inti saya .github.com / 3429822 ) mencakup lebih baik.
vorburger
Untuk tujuan apa? Jika Anda hanya ingin mencari soket kosong untuk didengarkan, cukup tentukan nol. Teknik pemindaian apa pun bertanggung jawab atas masalah jendela waktu: port bisa kosong saat Anda memindai dan ditempati saat Anda pergi untuk mengklaim masuk.
/**
* Checks to see if a specific port is available.
*
* @param port the port to check for availability
*/publicstaticboolean available(int port){if(port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER){thrownewIllegalArgumentException("Invalid start port: "+ port);}ServerSocket ss =null;DatagramSocket ds =null;try{
ss =newServerSocket(port);
ss.setReuseAddress(true);
ds =newDatagramSocket(port);
ds.setReuseAddress(true);returntrue;}catch(IOException e){}finally{if(ds !=null){
ds.close();}if(ss !=null){try{
ss.close();}catch(IOException e){/* should not be thrown */}}}returnfalse;}
Mereka juga memeriksa DatagramSocket untuk memeriksa apakah port tersedia di UDP dan TCP.
Varian yang bagus dari ini jika Anda memiliki MINA adalah AvailablePortFinder.getNextAvailable (1024) yang memberi Anda port non-hak istimewa berikutnya.
Alain O'Dea
9
Namun ini tidak menangkap semuanya. Saya telah digigit oleh nginx yang sedang berjalan di TCP 8000 sementara laporan rutin di atas 8000 tersedia. Tidak tahu mengapa - Saya curiga nginx melakukan beberapa hal licik (ini ada di OS X). Solusi bagi saya adalah melakukan hal di atas dan juga membuka Socket baru ("localhost", port) lalu mengembalikan false jika kita tidak mendapatkan pengecualian. Pikiran?
Mendung Sebagian
2
Masalah yang sama pada Windows mencoba mendeteksi apakah server SMTP potongan kertas sedang berjalan. Solusi di mana Anda membuka koneksi ke port, daripada mencoba mengikatnya (seperti yang disarankan oleh komentar Partly Clodys dan jawaban Ivan) tampaknya bekerja lebih andal.
stian
4
Menarik. Panggilan ke setReuseAddress () sama sekali tidak berguna setelah soket sudah terikat, dan itu juga sepenuhnya bertentangan dengan tujuan kode.
Marquis dari Lorne
3
Kode ini tunduk pada masalah waktu-jendela. Jika tujuannya adalah untuk membuat ServerSocketport listening ke beberapa, itulah yang harus dilakukan, dan mengembalikan ServerSocket. Membuatnya dan kemudian menutupnya dan mengembalikannya memberikan jaminan nol bahwa berikutnya ServerSocketdapat dibuat menggunakan port itu. Ditto for DatagramSocket.
Marquis dari Lorne
41
Untuk Java 7 Anda dapat menggunakan try-with-resource untuk kode yang lebih ringkas:
Ini tidak menguji apakah di port tersedia. Ini menguji apakah dalam status DENGARKAN, apakah alamat IP dapat dijangkau, dll.
Marquis dari Lorne
1
Selain itu tes ini cukup lambat (hampir satu detik per port).
JMax
bukankah seharusnya itu mengembalikan false ketika IOException tertangkap?
Baroudi Safwen
@BaroudiSafwen Itu sepenuhnya tergantung pada apa pengecualian sebenarnya. Karena ConnectException: 'connection refused', ya itu harus mengembalikan salah. Untuk waktu tunggu, tidak ada yang bisa dikembalikan yang valid, karena jawaban sebenarnya tidak diketahui. Itulah mengapa teknik ini tidak berguna untuk tujuan ini.
Marquis dari Lorne
36
Tampaknya mulai Java 7, jawaban David Santamaria tidak berfungsi lagi. Namun, sepertinya Anda masih dapat menggunakan Socket untuk menguji koneksi.
privatestaticboolean available(int port){System.out.println("--------------Testing port "+ port);Socket s =null;try{
s =newSocket("localhost", port);// If the code makes it this far without an exception it means// something is using the port and has responded.System.out.println("--------------Port "+ port +" is not available");returnfalse;}catch(IOException e){System.out.println("--------------Port "+ port +" is available");returntrue;}finally{if( s !=null){try{
s.close();}catch(IOException e){thrownewRuntimeException("You should handle this error.", e);}}}}
Saya ingin memeriksa apakah server proxy tersedia untuk melakukan panggilan atas namanya.
Dejell
1
Jawaban @ DavidSantamaria tidak pernah berhasil. Tidak ada hubungannya dengan Java 7.
Marquis dari Lorne
35
Jika Anda tidak terlalu peduli dengan kinerja, Anda selalu dapat mencoba mendengarkan di port menggunakan kelas ServerSocket . Jika itu melempar pengecualian kemungkinan itu sedang digunakan.
Gunakan akhirnya untuk pembersihan (coba {...} tangkap {...} akhirnya {if (socket! = Null) socket.close ();}
Hosam Aly
Anda juga dapat mengatur "portTaken = (socket == null);" di akhir alih-alih melakukannya di tangkapan.
Hosam Aly
1
Saya tidak merasa itu termasuk dalam cakupan pertanyaan penulis yang dimaksudkan.
Spencer Ruport
1
Apakah ada cara untuk melakukannya tanpa mencoba / menangkap? Saya tidak keberatan menggunakan setiap port yang tersedia untuk tujuan saya, tetapi iterasi nomor port dan mencoba / catch-ing lebih masing-masing sampai aku menemukan satu gratis adalah boros sedikit. Apakah tidak ada metode 'native boolean available (int)' di suatu tempat, yang hanya memeriksa?
Oren Shalev
27
SeverSocket baru (0) akan secara otomatis memilih port gratis.
Spencer Ruport
10
Solusi berikut ini terinspirasi oleh implementasi SocketUtils dari Spring-core (lisensi Apache).
Dibandingkan dengan solusi lain yang menggunakannya Socket(...)cukup cepat (menguji 1000 port TCP dalam waktu kurang dari satu detik):
publicstaticboolean isTcpPortAvailable(int port){try(ServerSocket serverSocket =newServerSocket()){// setReuseAddress(false) is required only on OSX, // otherwise the code will not work correctly on that platform
serverSocket.setReuseAddress(false);
serverSocket.bind(newInetSocketAddress(InetAddress.getByName("localhost"), port),1);returntrue;}catch(Exception ex){returnfalse;}}
Solusi berbasis soket coba / tangkap, mungkin tidak memberikan hasil yang akurat (alamat soket adalah "localhost" dan dalam beberapa kasus port dapat "ditempati" bukan oleh antarmuka loopback dan setidaknya pada Windows saya telah melihat tes ini gagal yaitu prot secara salah dinyatakan sebagai tersedia).
Ada perpustakaan keren bernama SIGAR , kode berikut dapat menghubungkan Anda:
Saya mendapatkan: "tidak ada sigar-x86-winnt.dll di java.library.path" Sayangnya itu membutuhkan download dari beberapa dll tambahan yang tidak benar-benar layak di lingkungan perusahaan (saya tidak memiliki kendali atas sistem CI). Sangat buruk .... Terima kasih.
uthomas
@uthomas Saya rasa Anda masih memiliki kendali atas paket penerapan aplikasi Anda, jika demikian, Anda selalu dapat menyediakan DLL / SO runtime asli Sigar di dekat JAR Anda dan menyetel jalur lib JAVA secara pragmatis (melalui peretasan sederhana Anda dapat mempengaruhinya bahkan setelah Anda aplikasi telah diluncurkan oleh JVM).
Shmil The Cat
2
Pembersihan dari jawaban yang ditunjukkan oleh David Santamaria:
/**
* Check to see if a port is available.
*
* @param port
* the port to check for availability.
*/publicstaticboolean isPortAvailable(int port){try(var ss =newServerSocket(port); var ds =newDatagramSocket(port)){returntrue;}catch(IOException e){returnfalse;}}
Ini masih tunduk pada kondisi balapan yang ditunjukkan oleh pengguna207421 di komentar untuk jawaban David Santamaria (sesuatu bisa mengambil port setelah metode ini menutup ServerSocketdan DatagramSocketdan kembali).
Dalam kasus saya, ini membantu untuk mencoba dan menyambung ke port - jika layanan sudah ada, itu akan merespons.
try{
log.debug("{}: Checking if port open by trying to connect as a client", portNumber);Socket sock =newSocket("localhost", portNumber);
sock.close();
log.debug("{}: Someone responding on port - seems not open", portNumber);returnfalse;}catch(Exception e){if(e.getMessage().contains("refused")){returntrue;}
log.error("Troubles checking if port is open", e);thrownewRuntimeException(e);}
Ini berfungsi untuk port UDP. Pertanyaannya tampaknya tentang port TCP.
Marquis dari Lorne
-2
Saya telah mencoba sesuatu seperti ini dan bekerja sangat baik dengan saya
SocketSkt;String host ="localhost";int i =8983;// port no.try{System.out.println("Looking for "+ i);Skt=newSocket(host, i);System.out.println("There is a Server on port "+ i +" of "+ host);}catch(UnknownHostException e){System.out.println("Exception occured"+ e);}catch(IOException e){System.out.println("port is not used");}
Jawaban:
Ini adalah implementasi yang berasal dari proyek unta Apache :
Mereka juga memeriksa DatagramSocket untuk memeriksa apakah port tersedia di UDP dan TCP.
Semoga ini membantu.
sumber
ServerSocket
port listening ke beberapa, itulah yang harus dilakukan, dan mengembalikanServerSocket
. Membuatnya dan kemudian menutupnya dan mengembalikannya memberikan jaminan nol bahwa berikutnyaServerSocket
dapat dibuat menggunakan port itu. Ditto forDatagramSocket
.Untuk Java 7 Anda dapat menggunakan try-with-resource untuk kode yang lebih ringkas:
sumber
ConnectException: 'connection refused'
, ya itu harus mengembalikan salah. Untuk waktu tunggu, tidak ada yang bisa dikembalikan yang valid, karena jawaban sebenarnya tidak diketahui. Itulah mengapa teknik ini tidak berguna untuk tujuan ini.Tampaknya mulai Java 7, jawaban David Santamaria tidak berfungsi lagi. Namun, sepertinya Anda masih dapat menggunakan Socket untuk menguji koneksi.
sumber
Jika Anda tidak terlalu peduli dengan kinerja, Anda selalu dapat mencoba mendengarkan di port menggunakan kelas ServerSocket . Jika itu melempar pengecualian kemungkinan itu sedang digunakan.
EDIT: Jika semua yang Anda coba lakukan adalah memilih port gratis, maka
new ServerSocket(0)
akan menemukan satu untuk Anda.sumber
Solusi berikut ini terinspirasi oleh implementasi SocketUtils dari Spring-core (lisensi Apache).
Dibandingkan dengan solusi lain yang menggunakannya
Socket(...)
cukup cepat (menguji 1000 port TCP dalam waktu kurang dari satu detik):sumber
Solusi berbasis soket coba / tangkap, mungkin tidak memberikan hasil yang akurat (alamat soket adalah "localhost" dan dalam beberapa kasus port dapat "ditempati" bukan oleh antarmuka loopback dan setidaknya pada Windows saya telah melihat tes ini gagal yaitu prot secara salah dinyatakan sebagai tersedia).
Ada perpustakaan keren bernama SIGAR , kode berikut dapat menghubungkan Anda:
sumber
Pembersihan dari jawaban yang ditunjukkan oleh David Santamaria:
Ini masih tunduk pada kondisi balapan yang ditunjukkan oleh pengguna207421 di komentar untuk jawaban David Santamaria (sesuatu bisa mengambil port setelah metode ini menutup
ServerSocket
danDatagramSocket
dan kembali).sumber
Dalam kasus saya, ini membantu untuk mencoba dan menyambung ke port - jika layanan sudah ada, itu akan merespons.
sumber
Dalam kasus saya, saya harus menggunakan kelas DatagramSocket.
Jangan lupa import dulu
sumber
Saya telah mencoba sesuatu seperti ini dan bekerja sangat baik dengan saya
sumber