Mengatur batas waktu untuk operasi soket

87

Saat saya membuat soket:

Socket socket = new Socket(ipAddress, port);

Ini melontarkan pengecualian, yang tidak masalah, karena alamat IP tidak tersedia. (Variabel uji dimana String ipAddress = "192.168.0.3"dan int port = 300.)

Masalahnya adalah: bagaimana cara mengaturnya ke batas waktu untuk soket itu?

Saat saya membuat soket, bagaimana cara mengurangi waktu sebelum saya mendapatkan UnknownHostExceptiondan mendapatkan soket ke waktu habis?

Jennifer
sumber
10
@adrianboimvaser: Jika demikian, Anda harus menandai sebagai duplikat, dan meninggalkan komentar yang menunjuk ke duplikat tersebut, sehingga moderator dapat menutupnya seperti itu (Anda meninggalkan komentar itu setahun yang lalu - mungkin Anda sudah mengetahuinya sekarang). Saya akan memberikan suara saya untuk melakukan itu sekarang, tetapi saya tidak tahu di mana duplikatnya!
Tom Anderson
1
Untuk melanjutkan tren menjawab terlambat bertahun-tahun, @EJP judul pertanyaan ini jauh lebih tidak ambigu daripada duplikat yang Anda sarankan
Isaac
@Isaac Dan sebenarnya itu sama sekali bukan duplikat, komentar ditarik.
pengguna207421
(Catatan: Saya telah mengubah judul agar tidak terlalu ambigu.)
Stephen C

Jawaban:

167

Gunakan Socket()konstruktor , dan connect(SocketAddress endpoint, int timeout)metode sebagai gantinya.

Dalam kasus Anda, ini akan terlihat seperti:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

Mengutip dari dokumentasi

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

Menghubungkan soket ini ke server dengan nilai batas waktu yang ditentukan. Waktu tunggu nol diartikan sebagai batas waktu tak terbatas. Koneksi kemudian akan memblokir hingga terbentuk atau terjadi kesalahan.

Parameter:

endpoint- SocketAddress
timeout- nilai batas waktu yang akan digunakan dalam milidetik.

Melempar:

IOException- jika kesalahan terjadi selama koneksi
SocketTimeoutException- jika batas waktu habis sebelum menghubungkan
IllegalBlockingModeException- jika soket ini memiliki saluran terkait, dan saluran dalam mode non-pemblokiran
IllegalArgumentException- jika titik akhir null atau subkelas SocketAddress tidak didukung oleh soket ini

Sejak: 1.4

aioobe
sumber
4
Ini dapat mengurangi waktu tunggu untuk ConnectException (tetapi tidak meningkatkannya), dan tidak berpengaruh pada batas waktu untuk UnknownHostException, yang diklaim oleh OP yang dia dapatkan (meskipun saya tidak percaya). Perhatikan juga bahwa Javadoc salah dalam menyatakan bahwa defaultnya adalah tak terbatas. Tidak. Platform memiliki batas waktu default sekitar satu menit, dan ini tidak dapat ditingkatkan.
pengguna207421
3
Bahkan setelah 4 tahun ini membantu, ini harus menjadi jawaban yang diterima.
Sharp Edge
4
Sekarang setelah 5 tahun dan ini adalah jawaban terbaik yang saya temukan di Internet .. Terima kasih
MBH
1
Penting juga untuk meminta socket.setSoTimeout(timeoutMillis)waktu tunggu selama pemblokiran operasi IO.
Abu
43

Anda tidak menetapkan batas waktu untuk soket, Anda menetapkan batas waktu untuk operasi yang Anda lakukan pada soket itu.

Sebagai contoh socket.connect(otherAddress, timeout)

Atau socket.setSoTimeout(timeout)untuk mengatur waktu tunggu pada read()operasi.

Lihat: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html

payne
sumber
Nah, dalam hal ini juga merupakan operasi, menghubungkan. Saya tidak dapat menemukan tempat yang menyatakan bahwa ctor ini menggunakan batas waktu tak terbatas meskipun tampaknya demikian.
sandos
3
@sandos Jelas dinyatakan dalam Javadoc untuk connect (). Namun itu juga tidak benar. Batas waktu default adalah batas waktu platform, sekitar satu menit, bukan tak terhingga, dan hanya bisa dikurangi dengan metode connect () ini, bukan ditambah.
pengguna207421
catatan, socket.setSoTimeoutharus dipanggil SETELAH connect, atau itu tidak akan berpengaruh dan pembacaan tidak akan pernah habis. ini adalah salah satu gotcha yang didokumentasikan dengan buruk.
pstanton
19

Anda dapat menggunakan solusi berikut:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

Semoga membantu!

karang
sumber
1
Jika, seperti yang dia klaim, dia mendapatkan UnknownHostException, itu akan terjadi pada baris pertama, di mana tidak ada perubahan batas waktu yang berlaku.
pengguna207421
Namun, baris pertama tidak mengeluarkan pengecualian apa pun. Dari dokumentasi: "Upaya akan dilakukan untuk menyelesaikan nama host menjadi InetAddress. Jika upaya itu gagal, alamat akan ditandai sebagai belum terselesaikan"
ady
Dalam hal ini, itu akan diselesaikan dengan connect()metode, tetapi tidak di bawah kendali batas waktu.
pengguna207421
8

Anda tidak dapat mengontrol waktu tunggu karena UnknownHostException. Ini adalah pengaturan waktu DNS. Anda hanya dapat mengontrol waktu tunggu koneksi yang diberikan host yang valid. Tak satu pun dari jawaban sebelumnya membahas hal ini dengan benar.

Tetapi saya merasa sulit untuk percaya bahwa Anda benar-benar mendapatkan UnknownHostExceptionketika Anda menentukan alamat IP daripada nama host.

EDIT Untuk mengontrol batas waktu DNS Java, lihat jawaban ini .

pengguna207421
sumber