java.net.SocketException: Bağlantı sıfırlama


128

Bir soketten okumaya çalışırken aşağıdaki hatayı alıyorum. Bunun readInt()üzerine bir yapıyorum InputStreamve bu hatayı alıyorum. Belgelere bakıldığında, bu, bağlantının istemci kısmının bağlantıyı kapattığını gösterir. Bu senaryoda sunucuyum.

İstemci günlük dosyalarına erişimim var ve bu bağlantıyı kapatmıyor ve aslında günlük dosyaları bağlantıyı kapatmamı öneriyor. Peki bunun neden olduğu hakkında bir fikri olan var mı? Kontrol edilecek başka ne var? Bu, eşik değerlere ulaşan yerel kaynaklar olduğunda ortaya çıkıyor mu?


Aşağıdaki satıra sahip olduğumu not ediyorum:

socket.setSoTimeout(10000);

hemen öncesinde readInt(). Bunun (uzun hikâye) bir nedeni var, ancak merak ediyorum, bunun belirtilen hataya yol açabileceği koşullar var mı? IDE'mde çalışan sunucu var ve IDE'mi bir kesme noktasında bıraktım ve daha sonra IDE'mde kendi günlüklerimde aynı hataların görünmeye başladığını fark ettim.

Her neyse, sadece bahsetmişken, umarım kırmızı ringa balığı değildir. :-(


Her iki taraftan yığın izleriniz var mı? Ağ mimarisini biraz daha tarif edebilir misiniz? (Vahşi İnternet üzerinden mi? Aynı makinede mi? Arada bir yerde mi?) Her zaman mı oluyor? Veya aralıklı olarak?
Stu Thompson

Yanıtlar:


116

Bunun birkaç olası nedeni vardır.

  1. Diğer uç, burada belgelemeyeceğim bir şekilde bağlantıyı kasıtlı olarak sıfırladı. Uygulama yazılımının bunu yapması nadirdir ve genellikle yanlıştır, ancak ticari yazılım için bilinmemektedir.

  2. Daha yaygın olarak, diğer ucun zaten normal olarak kapattığı bir bağlantıya yazılmasından kaynaklanır. Başka bir deyişle, bir uygulama protokol hatası.

  3. Ayrıca, soket alma arabelleğinde okunmamış veri olduğunda bir soketin kapatılmasından da kaynaklanabilir.

  4. Windows'ta, "bağlantı sıfırlama" ile aynı olmayan "yazılım bağlantının kesilmesine neden oldu", sizin tarafınızdan gönderilen ağ sorunlarından kaynaklanır. Bununla ilgili bir Microsoft bilgi bankası makalesi var.


@MattLyons Teşekkürler. Bundan çok daha iyi MSDN makaleleri var. Açıkçası buna inanması zor buluyorum. Doğru kaynak ve hedef IP adresleri belirlenene kadar bağlantı bile olmayacaktır. Gördüğüm MSDN makaleleri, bağlantıyı zaman aşımına uğratan kalıcı ağ hatalarına atıfta bulunuyor.
Lorne Markisi

48

Bağlantı sıfırlama, basitçe bir TCP RST'nin alındığı anlamına gelir. Bu, eşiniz işleyemeyeceği verileri aldığında gerçekleşir ve bunun çeşitli nedenleri olabilir.

En basit olanı, soketi kapatmanız ve ardından çıkış akışına daha fazla veri yazmanızdır. Soketi kapatarak, arkadaşınıza konuşmayı bitirdiğinizi söylediniz ve bağlantınızı unutabilir. Yine de bu akışta daha fazla veri gönderdiğinizde, akran dinlemediğini size bildirmek için bir RST ile reddeder.

Diğer durumlarda, araya giren bir güvenlik duvarı veya hatta uzak ana bilgisayarın kendisi TCP bağlantınızı "unutabilir". Bu, uzun süre herhangi bir veri göndermezseniz (2 saat yaygın bir zaman aşımıdır) veya eş yeniden başlatıldığında ve etkin bağlantılarla ilgili bilgilerini kaybettiğinde ortaya çıkabilir. Bu geçersiz bağlantılardan birine veri göndermek de bir RST'ye neden olur.


Ek bilgilere yanıt olarak güncelleme:

İle ilgili işleminize yakından bakın SocketTimeoutException. Bu istisna, bir soket işleminde bloke edilirken yapılandırılmış zaman aşımı aşılırsa ortaya çıkar. Bu istisna atıldığında soketin durumu değişmez, ancak istisna işleyiciniz soketi kapatır ve sonra ona yazmaya çalışırsa, bir bağlantı sıfırlama durumunda olursunuz. setSoTimeout()Bu, read()soketi başka bir iş parçacığından kapatmak gibi kirli şeyler yapmadan sonsuza kadar bloke edebilecek bir işlemden çıkmanız için size temiz bir yol sağlamak içindir .


Pek çok açıdan doğru değil. Çöp toplama ve işlem çıkışlarının her ikisi de düzgün kapanmalara neden olur, sıfırlamalara neden olmaz, ancak bir kapatma ve ardından eş tarafından bir yazma, EOS yerine sıfırlamayı tetikleyebilir. SocketTimeoutExceptions, yalnızca okuyucu bir okuma zaman aşımı ayarladıysa ortaya çıkar.
Marquis of Lorne

Ve her zaman bir RST alındığı anlamına gelmez. Aynı zamanda bu tarafın üretildiği anlamına da gelebilir.
Marquis of Lorne

17

Ne zaman böyle tuhaf sorunlar yaşasam , genellikle WireShark gibi bir araçla oturup ileri geri aktarılan ham verilere bakarım. Bir şeylerin bağlantısının kesildiği yerde şaşırabilirsiniz ve yalnızca denediğinizde ve okuduğunuzda size haber verilir .


10

Tam izi çok dikkatli incelemelisiniz,

Bir sunucu soket uygulamam var ve bir java.net.SocketException: Connection resetdurumu düzelttim .

Benim durumumda, bir sebepten Socketdolayı bağlantısını kapatan clientSocket nesnesinden okurken oluyor . (Ağ kaybı, güvenlik duvarı veya uygulama çökmesi veya amaçlanan kapanma)

Aslında bu Socket nesnesinden okurken bir hata aldığımda yeniden bağlantı kuruyordum.

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

İlginç olan şey, for my JAVA Socketbir istemcinin benim ServerSocketbağlantıma bağlanması ve is.read()özyinelemeli olarak herhangi bir çağrı göndermeden bağlantısını kapatmasıdır. Okuma işlemi için aşağıdaki gibi bir şey kullanırsanız;

while(true)
{
  Receive();
}

Sonra bir yığın elde edersiniz Aşağıdaki gibi bir şeyi sürekli takip edin

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

Yaptığım şey sadece ServerSocket'i kapatmak ve bağlantımı yenilemek ve daha fazla gelen istemci bağlantısını beklemek

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


//...
}

Bu, bilinmeyen istemci soket kayıpları için bağlantımı yeniden kurar

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...
            }
        }

Başka bir yol bulamadım çünkü aşağıdaki resimde gördüğünüz gibi bağlantının kopup kaybolmadığını anlayamıyorsunuz try and catch, çünkü her şey doğru görünüyor. Bu anlık görüntüyü Connection resetsürekli alırken aldım .

görüntü açıklamasını buraya girin


9

Bunu söylemek utanç verici, ama bu sorunu yaşadığımda, tüm verileri okumadan önce bağlantıyı kapatmam bir hataydı. Küçük dizelerin döndürüldüğü durumlarda işe yaradı, ancak bunun nedeni muhtemelen ben kapatmadan önce tüm yanıtın arabelleğe alınmış olmasıydı.

Daha uzun metin miktarlarının döndürülmesi durumunda, daha sonra bir arabellek geri geldiği için istisna atıldı.

Bu gözetimi kontrol edebilirsiniz. Bir URL açmanın bir dosya gibi olduğunu unutmayın, tamamen okunduktan sonra onu kapattığınızdan (bağlantıyı kesin) emin olun.


6

Ben de aynı hatayı aldım. Sorunun çözümünü şimdi buldum. Sorun, istemci programının sunucu akışları okumadan önce bitmesiydi.


Bu kendi başına bu istisnaya neden olmaz.
Marquis of Lorne

System.exit (0) programı sonlandırırsa ve bağlantı kötü durumda olduğundan ve düzgün kapatılmadığından kimse socket.close () öğesini çağırmazsa olur. sooo daha doğru bir şekilde, soketleri kapatmadan kapanan bir istemci programı olduğunu söyledi;) bu kötü bir şey ve düzeltilmesi gerekiyor.
Dekan Hiller

1
@DeanHiller Hayır olmaz. İşletim sistemi, soketi uygulamanın olması gerektiği şekilde kapatır.
Marquis of Lorne

@EJP .... Emin değilim ... Sadece System.exit ile yeniden üretebileceğimizi biliyorum ama OS / config'i hatırlamıyorum, çünkü epey zaman önce .... socket.close ( ) sunucudaki bağlantının sıfırlanmasını engelledi ve daha düzgün davrandı.
Dekan Hiller

2
@DeanHiller Yazma işlemi bitmeden okuma işleminden çıkıldı.
Marquis of Lorne

4

Java ile yazılmış bir SOA sistemiyle bu sorunu yaşadım. Hem istemciyi hem de sunucuyu farklı fiziksel makinelerde çalıştırıyordum ve uzun süre iyi çalıştılar, sonra bu kötü bağlantı sıfırlamaları istemci günlüğünde belirdi ve sunucu günlüğünde garip bir şey yoktu. Hem istemciyi hem de sunucuyu yeniden başlatmak sorunu çözmedi. Sonunda, sunucu tarafındaki yığının oldukça dolu olduğunu keşfettik, bu nedenle JVM için kullanılabilir belleği artırdık: sorun çözüldü! Günlükte OutOfMemoryError olmadığını unutmayın: bellek yetersizdi, tükenmemişti.


2

Sunucunuzun Java sürümünü kontrol edin. Benim başıma geldi çünkü Weblogic 10.3.6'm TLSv1'de olan JDK 1.7.0_75 üzerindeydi. Kullanmaya çalıştığım geri kalan uç nokta, TLSv1.2'nin altındaki herhangi bir şeyi kapatıyordu.

Varsayılan olarak Weblogic, en güçlü paylaşılan protokol üzerinde anlaşmaya çalışıyordu. Ayrıntılara buradan bakın: HTTPS bağlantıları için https.protocols Sistem Özelliğini ayarlamayla ilgili sorunlar .

Desteklenen TLS'yi belirlemek için ayrıntılı SSL günlük kaydı ekledim. Bu, el sıkışma için TLSv1'in kullanıldığını gösterdi.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Bu sorunu, özelliği JDK8 uyumlu ürünümüze aktararak çözdüm, JDK8 varsayılan olarak TLSv1.2'ye geçiyor. JDK7 ile sınırlı olanlar için, TLSv1.2'ye yükselterek Java 7 için bir geçici çözümü de başarıyla test ettim. Bu cevabı kullandım: Java 7'de TLS 1.2 nasıl etkinleştirilir


çok teşekkürler, sorunumu düzeltmek için bana yeni bir yön gösteriyorsunuz. ve nihayet durumun böyle olduğunu buldum !!!
karl li

1

Ayrıca bir Java programında SSH aracılığıyla bir sunucuya komut göndermeye çalışırken bu sorunu yaşadım. Sorun, Java kodunu çalıştıran makineyle ilgiliydi. Uzak sunucuya bağlanma izni yoktu. Write () yöntemi iyi gidiyordu, ancak read () yöntemi bir java.net.SocketException: Bağlantı sıfırlandı. Bu sorunu istemci SSH anahtarını bilinen uzak sunucu anahtarlarına ekleyerek çözdüm.


0

Tecrübelerime göre aşağıdaki durumlarla sık sık karşılaşıyorum;

  1. Kurumsal bir şirkette çalışıyorsanız, ağ ve güvenlik ekibiyle iletişime geçin. Çünkü dış servislere yapılan taleplerde ilgili uç noktaya izin verilmesi gerekebilir .

  2. Diğer bir sorun da, uygulamanızın çalıştığı sunucuda SSL sertifikasının süresinin dolmuş olabilmesidir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.