Periksa tautan ini
http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html
EDIT :Ya saya bermaksud menambahkan lebih banyak tetapi harus memotongnya di sana karena keadaan darurat
Apakah Anda menutup soket sebelum mencoba menyambung kembali? Menutup akan memberi tahu sistem bahwa pasangan soket (ip/port) sekarang gratis.
Berikut adalah item tambahan yang juga dilihat:
- Jika port lokal sudah terhubung ke IP dan port jarak jauh yang diberikan (yaitu, sudah ada pasangan soket yang identik), Anda akan menerima kesalahan ini (lihat tautan bug di bawah).
- Mengikat alamat soket yang bukan alamat lokal akan menghasilkan kesalahan ini. jika alamat IP mesin adalah 127.0.0.1 dan 1.2.3.4, dan Anda mencoba mengikat ke 1.2.3.5, Anda akan mendapatkan kesalahan ini.
- EADDRNOTAVAIL:Alamat yang ditentukan tidak tersedia di mesin jarak jauh atau bidang alamat struktur nama semuanya nol.
Tautkan dengan bug yang mirip dengan milik Anda (jawabannya dekat dengan bagian bawah)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599
Tampaknya soket Anda pada dasarnya macet di salah satu status internal TCP dan menambahkan penundaan untuk penyambungan kembali dapat menyelesaikan masalah Anda seperti yang tampaknya telah dilakukan dalam laporan bug tersebut.
Jika Anda tidak ingin mengubah jumlah port sementara yang tersedia (seperti yang disarankan oleh David), atau Anda memerlukan lebih banyak koneksi daripada jumlah maksimum teoretis, ada dua metode lain untuk mengurangi jumlah port yang digunakan. Namun, mereka melakukan berbagai pelanggaran terhadap standar TCP, sehingga harus digunakan dengan hati-hati.
Yang pertama adalah mengaktifkan SO_LINGER
dengan batas waktu nol detik, memaksa TCP
tumpukan untuk mengirim paket RST dan mengosongkan status koneksi. Namun ada satu kehalusan:Anda harus memanggil shutdown
pada deskriptor file soket sebelum Anda close
, sehingga Anda memiliki kesempatan untuk mengirim FIN
paket sebelum RST
paket. Jadi kodenya akan terlihat seperti:
shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
(char *) &linger, sizeof(linger));
close(fd);
Server seharusnya hanya melihat koneksi prematur yang disetel ulang jika FIN
paket disusun ulang dengan RST
paket.
Lihat opsi TCP SO_LINGER (nol) - bila diperlukan untuk detail lebih lanjut. (Secara eksperimental, tidak masalah di mana Anda menyetel setsockopt
.)
Yang kedua adalah menggunakan SO_REUSEADDR
dan bind
eksplisit (bahkan jika Anda adalah kliennya), yang akan memungkinkan Linux untuk menggunakan kembali porta sementara saat Anda menjalankannya, sebelum selesai menunggu. Perhatikan bahwa Anda harus gunakan bind
dengan INADDR_ANY
dan port 0
, jika tidak SO_REUSEADDR
tidak dihormati. Kode Anda akan terlihat seperti:
int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &opts, sizeof(int));
struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));
// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
Opsi ini kurang bagus karena Anda masih akan memenuhi struktur data kernel internal untuk koneksi TCP sesuai netstat -an | grep -e tcp -e udp | wc -l
. Namun, Anda tidak akan mulai menggunakan kembali port hingga hal ini terjadi.
Ini juga dapat terjadi jika port yang diberikan tidak valid, seperti 0.