java.net.SocketException: Sambungan ulang

128

Saya mendapatkan kesalahan berikut saat mencoba membaca dari soket. Saya melakukan readInt()itu InputStream, dan saya mendapatkan kesalahan ini. Membaca dokumentasi dengan teliti, ini menunjukkan bahwa bagian klien dari koneksi menutup koneksi. Dalam skenario ini, saya adalah server.

Saya memiliki akses ke file log klien dan tidak menutup koneksi, dan sebenarnya file log-nya menyarankan saya menutup koneksi. Jadi, apakah ada yang tahu mengapa ini terjadi? Apa lagi yang harus diperiksa? Apakah ini muncul ketika ada sumber daya lokal yang mungkin mencapai ambang batas?


Saya perhatikan bahwa saya memiliki baris berikut:

socket.setSoTimeout(10000);

tepat sebelum readInt(). Ada alasan untuk ini (cerita panjang), tetapi hanya penasaran, adakah keadaan di mana hal ini dapat menyebabkan kesalahan yang ditunjukkan? Saya memiliki server yang berjalan di IDE saya, dan saya membiarkan IDE saya macet di breakpoint, dan saya kemudian melihat kesalahan yang sama persis mulai muncul di log saya sendiri di IDE saya.

Ngomong-ngomong, sebutkan saja, semoga bukan ikan haring merah. :-(

kebiruan
sumber
Apakah Anda memiliki jejak tumpukan dari kedua sisi? Dapatkah Anda menjelaskan lebih banyak tentang arsitektur jaringan? (Melalui Internet liar? Di mesin yang sama? Di suatu tempat di antara keduanya?) Apakah itu terjadi sepanjang waktu? Atau sesekali?
Stu Thompson

Jawaban:

116

Ada beberapa kemungkinan penyebabnya.

  1. Ujung lainnya dengan sengaja mengatur ulang koneksi, dengan cara yang tidak akan saya dokumentasikan di sini. Jarang, dan umumnya tidak benar, perangkat lunak aplikasi melakukan ini, tetapi perangkat lunak komersial tidak dikenal.

  2. Lebih umum, ini disebabkan oleh penulisan ke koneksi yang ujung lainnya sudah ditutup secara normal. Dengan kata lain kesalahan protokol aplikasi.

  3. Ini juga dapat disebabkan oleh penutupan soket ketika ada data yang belum dibaca di soket penerima penerima.

  4. Di Windows, 'perangkat lunak menyebabkan koneksi dibatalkan', yang tidak sama dengan 'reset koneksi', disebabkan oleh masalah jaringan yang dikirim dari pihak Anda. Ada artikel basis pengetahuan Microsoft tentang ini.

Marquis dari Lorne
sumber
Terima kasih @attLy. Ada artikel MSDN yang jauh lebih baik dari itu. Terus terang saya merasa itu sulit dipercaya. Koneksi bahkan tidak akan ada sampai alamat IP sumber dan target yang benar telah dibuat. Artikel MSDN yang saya lihat mengacu pada kesalahan jaringan yang terus-menerus saat keluar dari sambungan.
Marquis dari Lorne
48

Reset koneksi berarti bahwa TCP RST telah diterima. Ini terjadi ketika rekan Anda menerima data yang tidak dapat diproses, dan ada berbagai alasan untuk itu.

Yang paling sederhana adalah ketika Anda menutup soket, dan kemudian menulis lebih banyak data pada aliran keluaran. Dengan menutup soket, Anda memberi tahu rekan Anda bahwa Anda selesai berbicara, dan itu dapat melupakan koneksi Anda. Saat Anda tetap mengirim lebih banyak data pada streaming itu, peer menolaknya dengan RST untuk memberi tahu Anda bahwa streaming tidak mendengarkan.

Dalam kasus lain, firewall yang mengganggu atau bahkan host jarak jauh itu sendiri mungkin "lupa" tentang koneksi TCP Anda. Ini dapat terjadi jika Anda tidak mengirim data apa pun untuk waktu yang lama (2 jam adalah waktu tunggu yang umum), atau karena rekan di-boot ulang dan kehilangan informasinya tentang koneksi aktif. Mengirim data pada salah satu koneksi yang tidak berfungsi ini akan menyebabkan RST juga.


Pembaruan sebagai tanggapan atas informasi tambahan:

Perhatikan baik-baik penanganan Anda terhadap SocketTimeoutException. Pengecualian ini dimunculkan jika batas waktu yang dikonfigurasi terlampaui saat diblokir pada operasi soket. Status soket itu sendiri tidak berubah saat pengecualian ini dilemparkan, tetapi jika penangan pengecualian Anda menutup soket, dan kemudian mencoba untuk menulis padanya, Anda akan berada dalam kondisi reset koneksi. setSoTimeout()dimaksudkan untuk memberi Anda cara yang bersih untuk keluar dari read()operasi yang mungkin akan memblokir selamanya, tanpa melakukan hal-hal kotor seperti menutup soket dari thread lain.

erickson
sumber
Tidak benar dalam beberapa hal. Pengumpulan sampah dan proses keluar keduanya menyebabkan penutupan yang benar, bukan penyetelan ulang, tetapi penutupan yang diikuti oleh penulisan oleh rekan dapat menyebabkan penyetelan ulang daripada EOS. SocketTimeoutExceptions hanya dimunculkan jika pembaca telah menyetel batas waktu baca.
Marquis dari Lorne
Dan itu tidak selalu berarti RST telah diterima. Ini juga bisa berarti satu dibuat oleh sisi ini.
Marquis dari Lorne
17

Setiap kali saya mengalami masalah aneh seperti ini, saya biasanya duduk dengan alat seperti WireShark dan melihat data mentah yang diteruskan bolak-balik. Anda mungkin terkejut ketika ada hal-hal yang terputus, dan Anda hanya diberi tahu saat Anda mencoba dan membaca.

GEOCHET
sumber
9

Memalukan untuk mengatakannya, tetapi ketika saya mengalami masalah ini, itu hanyalah kesalahan bahwa saya menutup koneksi sebelum saya membaca semua data. Dalam kasus dengan string kecil dikembalikan, itu berhasil, tetapi itu mungkin karena seluruh respons di-buffer, sebelum saya menutupnya.

Dalam kasus jumlah teks yang lebih panjang dikembalikan, pengecualian dilemparkan, karena lebih dari itu penyangga kembali.

Anda mungkin memeriksa pengawasan ini. Ingat membuka URL seperti file, pastikan untuk menutupnya (melepaskan koneksi) setelah selesai dibaca.

Scott S.
sumber
9

Anda harus memeriksa jejak lengkap dengan sangat hati-hati,

Saya memiliki aplikasi soket server dan memperbaiki java.net.SocketException: Connection resetkasus.

Dalam kasus saya itu terjadi saat membaca dari Socketobjek clientSocket yang ditutup koneksinya karena beberapa alasan. (Jaringan hilang, firewall atau aplikasi crash atau penutupan yang dimaksudkan)

Sebenarnya saya sedang membangun kembali koneksi ketika saya mendapat kesalahan saat membaca dari objek Socket ini.

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

Hal yang menarik adalah for my JAVA Socketjika klien terhubung ke my ServerSocketdan menutup koneksinya tanpa mengirim is.read()panggilan apa pun secara rekursif. Tampaknya karena berada dalam loop sementara yang tak terbatas untuk membaca dari soket ini, Anda mencoba membaca dari koneksi tertutup. Jika Anda menggunakan sesuatu seperti di bawah ini untuk operasi baca;

while(true)
{
  Receive();
}

Kemudian Anda mendapatkan stackTrace seperti di bawah ini dan seterusnya

java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

Apa yang saya lakukan hanyalah menutup ServerSocket dan memperbarui koneksi saya dan menunggu koneksi klien masuk lebih lanjut

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

Ini memulihkan koneksi saya untuk soket klien yang tidak diketahui hilang

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

Saya tidak dapat menemukan cara lain karena seperti yang Anda lihat dari gambar di bawah ini Anda tidak dapat memahami apakah koneksi terputus atau tidak tanpa try and catch, karena semuanya tampak benar. Saya mendapatkan foto ini saat saya Connection resetterus melanjutkan.

masukkan deskripsi gambar di sini

Davut Gürbüz
sumber
6

Saya mengalami kesalahan yang sama. Saya menemukan solusi untuk masalah sekarang. Masalahnya adalah program klien selesai sebelum server membaca aliran.

kml_ckr
sumber
Itu tidak akan menyebabkan pengecualian ini dengan sendirinya.
Marquis dari Lorne
itu akan terjadi jika System.exit (0) mematikan program dan tidak ada yang memanggil socket.close () karena koneksi dalam keadaan buruk dan tidak ditutup dengan benar. sooo lebih tepat mengatakan dia memiliki program klien yang mematikan tanpa menutup soket;) yang merupakan hal yang buruk dan harus diperbaiki.
Dean Hiller
1
@DeanTidak. Sistem operasi akan menutup soket dengan cara yang sama seperti yang harus dimiliki aplikasi.
Marquis dari Lorne
@EJP .... Saya tidak yakin ... Saya baru tahu kami dapat mereproduksinya dengan System.exit tetapi saya tidak ingat OS / config karena beberapa waktu yang lalu .... memanggil socket.close ( ) di server mencegah koneksi ulang dan itu berperilaku lebih baik.
Dean Hiller
2
@DeanHiller Proses membaca dilakukan sebelum proses menulis selesai menulis.
Marquis dari Lorne
4

Saya mengalami masalah ini dengan sistem SOA yang ditulis di Java. Saya menjalankan klien dan server pada mesin fisik yang berbeda dan mereka bekerja dengan baik untuk waktu yang lama, kemudian pengaturan ulang koneksi yang buruk itu muncul di log klien dan tidak ada yang aneh di log server. Memulai ulang klien dan server tidak menyelesaikan masalah. Akhirnya kami menemukan bahwa heap di sisi server agak penuh sehingga kami meningkatkan memori yang tersedia untuk JVM: masalah terpecahkan! Perhatikan bahwa tidak ada OutOfMemoryError di log: memori hanya langka, tidak habis.

Pino
sumber
2

Periksa versi Java server Anda. Terjadi pada saya karena Weblogic 10.3.6 saya menggunakan JDK 1.7.0_75 yang ada di TLSv1. Titik akhir lainnya yang saya coba konsumsi adalah mematikan apa pun di bawah TLSv1.2.

Secara default Weblogic mencoba menegosiasikan protokol bersama terkuat. Lihat detailnya di sini: Masalah dengan pengaturan https.protocols System Property untuk koneksi HTTPS .

Saya menambahkan logging SSL verbose untuk mengidentifikasi TLS yang didukung. Ini menunjukkan TLSv1 sedang digunakan untuk jabat tangan.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Saya menyelesaikan ini dengan mendorong fitur ke produk kami yang kompatibel dengan JDK8, JDK8 default ke TLSv1.2. Bagi mereka yang dibatasi untuk JDK7, saya juga berhasil menguji solusi untuk Java 7 dengan meningkatkan ke TLSv1.2. Saya menggunakan jawaban ini: Cara mengaktifkan TLS 1.2 di Java 7

Sumiya
sumber
terima kasih banyak, Anda menunjukkan arah baru untuk memperbaiki masalah saya. dan akhirnya saya menemukan itu masalahnya !!!
karl li
1

Saya juga mengalami masalah ini dengan program Java yang mencoba mengirim perintah di server melalui SSH. Masalahnya ada pada mesin yang menjalankan kode Java. Itu tidak memiliki izin untuk terhubung ke server jarak jauh. Metode write () baik-baik saja, tetapi metode read () melempar java.net.SocketException: Connection reset. Saya memperbaiki masalah ini dengan menambahkan kunci SSH klien ke kunci yang dikenal server jauh.

pmartin8
sumber
0

Dalam pengalaman saya, saya sering menghadapi situasi berikut;

  1. Jika Anda bekerja di perusahaan korporat, hubungi jaringan dan tim keamanan. Karena dalam permintaan yang dibuat ke layanan eksternal, mungkin perlu memberikan izin untuk titik akhir yang relevan.

  2. Masalah lainnya adalah bahwa sertifikat SSL mungkin telah kedaluwarsa di server tempat aplikasi Anda berjalan.

bmck
sumber