G / Ç girişiminde bulunmadan, TCP soketinin eş tarafından incelikle kapatıldığını tespit etmek neden imkansız?


93

A kadar takip ettikçe son soruya , bunun soket incelikle eş tarafından kapalı olduğunu tespit etmek için, bir TCP soket üzerinde okuma / yazma girişiminde olmadan, Java imkansızdır neden acaba? Ön NIO Socketveya NIO kullanılıp kullanılmadığına bakılmaksızın durum böyle görünüyor SocketChannel.

Bir eş, bir TCP bağlantısını incelikle kapattığında, TCP, bağlantının her iki tarafındaki yığınları gerçeği bilir. Sunucu tarafı (kapatmayı başlatan) durumda biterken FIN_WAIT2, istemci tarafı (kapatmaya açık bir şekilde yanıt vermeyen) durumda sona erer CLOSE_WAIT. Neden bir yöntem yoktur Socketya da SocketChannelaltta yatan bir TCP bağlantı sonlandırıldı olup olmadığını görmek için TCP yığını sorgulayabilir? TCP yığını böyle bir durum bilgisi sağlamıyor mu? Yoksa çekirdeğe yapılan maliyetli bir çağrıyı önlemek için bir tasarım kararı mı?

Bu soruya daha önce bazı cevaplar göndermiş olan kullanıcıların yardımıyla, sorunun nereden kaynaklanıyor olabileceğini düşünüyorum. Bağlantıyı açıkça kapatmayan taraf TCP durumunda sona erer, CLOSE_WAITbu da bağlantının kapanma sürecinde olduğu ve tarafın kendi CLOSEişlemini gerçekleştirmesini bekler . O 's adil yeterince varsayalım isConnecteddöner trueve isCloseddöner false, ama neden böyle orada bir şey değildir isClosing?

NIO öncesi soketleri kullanan test sınıfları aşağıdadır. Ancak aynı sonuçlar NIO kullanılarak elde edilir.

import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
  public static void main(String[] args) throws Exception {
    final ServerSocket ss = new ServerSocket(12345);
    final Socket cs = ss.accept();
    System.out.println("Accepted connection");
    Thread.sleep(5000);
    cs.close();
    System.out.println("Closed connection");
    ss.close();
    Thread.sleep(100000);
  }
}


import java.net.Socket;

public class MyClient {
  public static void main(String[] args) throws Exception {
    final Socket s = new Socket("localhost", 12345);
    for (int i = 0; i < 10; i++) {
      System.out.println("connected: " + s.isConnected() + 
        ", closed: " + s.isClosed());
      Thread.sleep(1000);
    }
    Thread.sleep(100000);
  }
}

Test istemcisi test sunucusuna bağlandığında, sunucu bağlantıyı kapattıktan sonra bile çıktı değişmeden kalır:

connected: true, closed: false
connected: true, closed: false
...

Şunu söylemeliyim: SCTP protokolünde bu "sorun" yok. SCTP, TCP gibi yarı kapalı bir duruma sahip değildir, başka bir deyişle, bir taraf veri göndermeye devam ederken diğer ucu gönderme yuvasını kapatmıştır. Bu işleri kolaylaştırmalı.
Tarnay Kálmán

2
İki Posta Kutumuz (Priz) var ........................................... ...... Posta Kutuları RoyalMail (IP) kullanarak birbirlerine posta gönderir TCP'yi unutun ............................. .................... Her şey yolunda ve zekice, posta kutuları herhangi bir sorunla karşılaşmadan birbirlerine posta gönderebilir / alabilir (son zamanlarda çok fazla gecikme). ............. Bir Posta Kutusu bir kamyona çarpıp başarısız olursa .... diğer Posta Kutusu nasıl bilebilirdi? Royal Mail tarafından bildirilmesi gerekecekti, o da bir sonraki başarısız Posta Kutusundan posta göndermeyi / almayı deneyene kadar bilmeyecekti .. ...... erm .....
divinci

Soketten okumayacaksanız veya sokete yazmayacaksanız, neden umursuyorsunuz? Ve eğer soketten okuyacaksanız veya sokete yazacaksanız, neden fazladan kontrol yapasınız? Kullanım durumu nedir?
David Schwartz

2
Socket.closezarif bir kapanış değil.
user253751

@immibis Alma arabelleğinde okunmamış veri yoksa veya SO_LINGER ile uğraşmadıysanız, kesinlikle zarif bir kapanış.
user207421

Yanıtlar:


29

Sıklıkla Soketleri kullanıyorum, çoğunlukla Seçicilerle ve bir Ağ OSI uzmanı olmasa da, anladığım kadarıyla, shutdownOutput()bir Soketi çağırmak aslında ağda (FIN) Seçicimi diğer tarafta uyandıran bir şey gönderiyor (C'deki aynı davranış dil). Burada algılama var : gerçekten denediğinizde başarısız olacak bir okuma işlemini algılamak.

Verdiğiniz kodda, soketin kapatılması hem giriş hem de çıkış akışlarını, mevcut olabilecek verileri okuma imkânı olmadan kapatacak ve dolayısıyla onları kaybetecektir. Java Socket.close()yöntemi, çıkış akışında bırakılan verinin , kapanışını bildirmek için bir FIN ile gönderileceği için "zarif" bir bağlantı kesme (ilk başta düşündüğümün tersi) gerçekleştirir . Herhangi bir normal paket 1 yapacağı gibi, FIN diğer taraf tarafından ACK'lanacaktır .

Diğer tarafın yuvasını kapatmasını beklemeniz gerekiyorsa, FIN için beklemeniz gerekir. Ve bu başarmak için, size gereken algılamak Socket.getInputStream().read() < 0yapmanız gerekir, yani değil o gibi, sizin soket yakın onun kapatınInputStream .

C'de ve şimdi Java'da yaptığımdan, böyle senkronize bir kapanma elde etmek şu şekilde yapılmalıdır:

  1. Kapatma soketi çıkışı (diğer uçta FIN gönderir, bu, bu soket tarafından gönderilecek son şeydir). Giriş hala açık, böylece read()uzaktan kumandayı görebilir ve algılayabilirsinizclose()
  2. Soketi InputStreamdiğer uçtan cevap-FIN'i alana kadar okuyun (FIN'i algılayacağı için aynı zarif bağlantı kesme sürecinden geçecektir). Bu, bazı işletim sistemlerinde önemlidir çünkü arabelleğinden biri hala veri içerdiği sürece soketi gerçekten kapatmazlar. Bunlara "hayalet" soket denir ve işletim sisteminde tanımlayıcı sayıları kullanır (bu artık modern işletim sistemlerinde bir sorun olmayabilir)
  3. (Ya arayarak soketi kapatın Socket.close()veya kapama onun InputStreamya OutputStream)

Aşağıdaki Java kod parçasında gösterildiği gibi:

public void synchronizedClose(Socket sok) {
    InputStream is = sok.getInputStream();
    sok.shutdownOutput(); // Sends the 'FIN' on the network
    while (is.read() > 0) ; // "read()" returns '-1' when the 'FIN' is reached
    sok.close(); // or is.close(); Now we can close the Socket
}

Elbette her iki taraf da aynı kapatma yöntemini kullanmak zorundadır veya gönderen taraf her zaman whiledöngüyü meşgul edecek kadar veri gönderiyor olabilir (örneğin, gönderen taraf yalnızca veri gönderiyorsa ve bağlantı sonlandırmayı algılamak için asla okumuyorsa. ancak bu konuda kontrole sahip olmayabilirsiniz).

@WarrenDew'in yorumunda belirttiği gibi, programdaki (uygulama katmanı) verilerin atılması, uygulama katmanında zarif olmayan bir bağlantı kesilmesine neden olur: tüm veriler TCP katmanında ( whiledöngü) alınmış olsa da , bunlar atılır.

1 : " Java'da Temel Ağ Oluşturma " bölümünden : bkz. Şek. 3.3 s. 45 ve tüm §3.7, s. 43-48


Java, zarif bir kapanış gerçekleştirir. Acımasız değil.
user207421

2
@EJP, "zarif bağlantı kesilmesi" TCP seviyesinde gerçekleşen özel bir değiş tokuş olup, İstemcinin Sunucuya bağlantıyı kesme isteğini işaret etmesi ve bunun sonucunda kalan verileri kendi tarafını kapatmadan önce gönderir. "Kalan verileri gönder" kısmı program tarafından ele alınmalıdır (ancak insanlar çoğu zaman hiçbir şey göndermezler). Çağrı socket.close(), bu İstemci / Sunucu sinyaline saygı göstermemesi açısından "acımasız" dır. Sunucuya bir İstemci bağlantısının kesilmesi konusunda yalnızca kendi soket çıktı tamponu dolduğunda bildirim gönderilir (çünkü kapatılmış olan diğer taraf tarafından hiçbir veri ele geçirilmez).
Matthieu

Daha fazla bilgi için MSDN'ye bakın .
Matthieu

1
@Matthieu Uygulamanız tüm mevcut verileri okumazsa, bu uygulama katmanında önemsiz olabilir, ancak TCP taşıma katmanında veriler yine de alınır ve bağlantı düzgün bir şekilde sonlandırılır. Aynı durum, uygulamanız giriş akışındaki tüm verileri okursa ve yalnızca atarsa ​​da geçerli olur.
Warren Dew

2
@LeonidUsov Bu tamamen yanlış. Java read(), akışın sonunda -1 değerini döndürür ve bunu birçok kez çağırırsanız yapmaya devam eder. Akışın sonunda AC read()veya recv()sıfır döndürür ve birçok kez çağırırsanız bunu yapmaya devam eder.
user207421

18

Bunun daha çok bir soket programlama sorusu olduğunu düşünüyorum. Java sadece soket programlama geleneğini takip ediyor.

Gönderen Vikipedi :

TCP, bir bilgisayardaki bir programdan başka bir bilgisayardaki başka bir programa güvenilir, sıralı bir bayt akışı sağlar.

El sıkışma yapıldığında, TCP iki uç nokta (istemci ve sunucu) arasında herhangi bir ayrım yapmaz. "İstemci" ve "sunucu" terimi çoğunlukla kolaylık sağlamak içindir. Bu nedenle, "sunucu" veri gönderiyor olabilir ve "istemci" bazı diğer verileri aynı anda birbirine gönderiyor olabilir.

"Kapat" terimi de yanıltıcıdır. Yalnızca FIN beyanı var, yani "Size daha fazla şey göndermeyeceğim." Ancak bu, uçuşta paket olmadığı veya diğerinin söyleyecek başka bir şey olmadığı anlamına gelmez. Veri bağlantı katmanı olarak salyangoz postası uygularsanız veya paketiniz farklı rotalarda seyahat ederse, alıcının paketleri yanlış sırada alması olasıdır. TCP bunu sizin için nasıl düzelteceğini bilir.

Ayrıca, bir program olarak, arabellekte ne olduğunu kontrol etmeye devam edecek zamanınız olmayabilir. Böylece, uygun olduğunuzda arabellekte ne olduğunu kontrol edebilirsiniz. Sonuç olarak, mevcut soket uygulaması o kadar da kötü değil. Gerçekte isPeerClosed () varsa, bu, oku aramak istediğiniz her seferinde yapmanız gereken fazladan çağrıdır.


1
Sanmıyorum, hem Windows hem de linux üzerinde C kodundaki durumları test edebilirsiniz !!! Java bazı nedenlerden ötürü bazı şeyleri açığa çıkarmayabilir, tıpkı windows ve linux üzerinde bulunan getsockopt işlevlerini açığa çıkarmak gibi. Aslında, aşağıdaki cevaplarda linux tarafı için bazı linux C kodları vardır.
Dekan Hiller

'İsPeerClosed ()' yöntemine sahip olmanın bir şekilde her okuma denemesinden önce onu çağırmanızı sağladığını düşünmüyorum. Sadece açıkça ihtiyacınız olduğunda çağırabilirsiniz. Soketin uzak kısmının kapalı olup olmadığını öğrenmek istiyorsanız çıkış akımına yazmanızı gerektirse de, mevcut soket uygulamasının o kadar da kötü olmadığını kabul ediyorum. Çünkü eğer değilse, yazılı verilerinizi diğer tarafta da işlemeniz gerekir ve bu dikey olarak yönlendirilmiş çivi üzerinde oturmak kadar büyük bir zevktir;)
Jan Hruby

1
Bu , 'uçuşta başka paket yok' anlamına gelir. FIN, uçuştaki herhangi bir veriden sonra alınır . Ancak ne yapmaz ortalama akran soket kapalı olmasıdır girişi için. Bunu algılamak için ** bir şey göndermeniz * ve bir 'bağlantıyı sıfırlamanız' gerekir. FIN sadece çıktı için bir kapanma anlamına gelebilirdi.
user207421

11

Temel soketler API'sinde böyle bir bildirim yoktur.

Gönderen TCP yığını, FIN bitini her halükarda son pakete kadar göndermez, bu nedenle, gönderen uygulama, bu veriler daha gönderilmeden önce mantıksal olarak soketini kapattığında arabelleğe alınan çok fazla veri olabilir. Aynı şekilde, ağ alıcı uygulamadan daha hızlı olduğu için arabelleğe alınan veriler (bilmiyorum, belki daha yavaş bir bağlantı üzerinden aktarıyorsunuzdur) alıcı için önemli olabilir ve alıcı uygulamanın onu atmasını istemezsiniz. sadece FIN biti yığın tarafından alındığı için.


Benim test örneğimde (belki burada bir tane sağlamalıyım ...) bilerek bağlantı üzerinden gönderilen / alınan veri yok. Bu nedenle, yığının FIN (zarif) veya RST (bazı zarif olmayan senaryolarda) aldığından oldukça eminim. Bu aynı zamanda netstat tarafından da onaylanmıştır.
Alexander

1
Elbette - hiçbir şey arabelleğe alınmazsa, FIN, aksi takdirde boş bir paket üzerinde (yüksüz) hemen gönderilecektir. FIN'den sonra, yine de, bağlantının bu ucundan daha fazla veri paketi gönderilmez (yine de kendisine gönderilen herhangi bir şeyi ACK'ye alır).
Mike Dimmick

1
Olan, bağlantının kenarlarının <code> CLOSE_WAIT </code> ve <code> FIN_WAIT_2 </code> ile bitmesi ve bu durumda <code> isConcected () </code> ve <code> isClosed () </code> hala bağlantının sonlandırıldığını görmüyor.
Alexander

Önerileriniz için teşekkürler! Sanırım sorunu şimdi daha iyi anlıyorum. Soruyu daha belirgin hale getirdim (üçüncü paragrafa bakın): yarı kapalı bağlantıları test etmek için neden "Socket.isClosing" yok?
Alexander

8

Şimdiye kadar hiçbir cevap soruyu tam olarak yanıtlamadığından, konuyla ilgili şu anki anlayışımı özetliyorum.

Bir TCP bağlantısı kurulduğunda ve bir eş aradığında close()veya shutdownOutput()soketinde, bağlantının diğer tarafındaki soket CLOSE_WAITduruma geçer. Prensip olarak, CLOSE_WAITçağrı yapmadan bir soketin durumda olup olmadığını TCP yığınından bulmak mümkündür read/recv(örneğin, getsockopt()Linux'ta: http://www.developerweb.net/forum/showthread.php?t=4395 ), ancak bu değil taşınabilir.

Java'nın Socketsınıfı, bir BSD TCP soketine benzer bir soyutlama sağlayacak şekilde tasarlanmış gibi görünmektedir, bunun nedeni muhtemelen bu, insanların TCP / IP uygulamalarını programlarken alıştıkları soyutlama düzeyidir. BSD soketleri, sadece INET (örneğin, TCP) soketlerinden farklı bir genellemeyi destekleyen soketlerdir, bu nedenle bir soketin TCP durumunu bulmak için taşınabilir bir yol sağlamazlar.

Gibi hiçbir yöntem yoktur isCloseWait()BSD soketleri tarafından sunulan soyutlama düzeyinde TCP uygulamalarını programlama için kullanılan insanlar Java herhangi bir ekstra yöntemler sağlamaktır beklemeyin çünkü.


3
Ne de olabilir Java portably, herhangi bir ekstra yöntemler sunar. Belki de platform desteklemediyse yanlış döndüren bir isCloseWait () yöntemi yapabilirler, ancak yalnızca desteklenen platformlarda test ederlerse kaç programcı bu getcha tarafından ısırılır?
ephemient


1
Programcılar buna alışkın değil; programcılar için yararlı olan şey soket arabirimidir. Soket soyutlamasının TCP protokolünden daha fazlası için kullanıldığını unutmayın.
Warren Dew

Java'da isCloseWait()tüm platformlarda desteklenmediği için böyle bir yöntem yoktur .
user207421

Ident (RFC 1413) protokolü, sunucunun bir yanıt gönderdikten sonra bağlantıyı açık tutmasına veya daha fazla veri göndermeden kapatmasına olanak tanır. Bir Java kimlik istemcisi, sonraki aramada 3 yönlü el sıkışmasını önlemek için bağlantıyı açık tutmayı seçebilir, ancak bağlantının hala açık olduğunu nasıl anlar? Bağlantıyı yeniden açarak herhangi bir hataya yanıt vermeyi denemeli mi? Yoksa bu bir protokol tasarım hatası mı?
david

7

Bir (TCP) soket bağlantısının uzak tarafının kapalı olup olmadığını tespit etmek java.net.Socket.sendUrgentData (int) yöntemiyle yapılabilir ve uzak taraf çalışmıyorsa IOException'ı yakalar. Bu, Java-Java ve Java-C arasında test edilmiştir.

Bu, bir çeşit ping mekanizması kullanmak için iletişim protokolünü tasarlama sorununu ortadan kaldırır. Bir soket üzerinde OOBInline'ı devre dışı bırakarak (setOOBInline (false), alınan tüm OOB verileri sessizce atılır, ancak OOB verileri yine de gönderilebilir. Uzak taraf kapatılırsa, bir bağlantı sıfırlama denenir, başarısız olur ve bazı IOException atılmasına neden olur .

Protokolünüzde gerçekten OOB verilerini kullanıyorsanız, kilometreniz değişebilir.


4

Java IO yığını, ani bir kopmada imha edildiğinde kesinlikle FIN gönderir. Bunu tespit edememeniz bir anlam ifade etmiyor, çünkü çoğu istemci yalnızca bağlantıyı kapatıyorlarsa FIN gönderir.

... NIO Java sınıflarından gerçekten nefret etmeye başlamamın başka bir nedeni. Görünüşe göre her şey biraz yarım yamalak.


1
ayrıca, bir FIN varken yalnızca okuma sırasında (-1 dönüş) alıyorum ve yayın sonunu alıyorum. Bu yüzden okuma tarafında bir kapanma tespit etmenin tek yolu bu.

3
Onu tespit edebilirsiniz. Okurken EOS alırsınız. Ve Java, FIN göndermez. TCP bunu yapar. Java, TCP / IP'yi uygulamaz, sadece platform uygulamasını kullanır.
user207421

4

Bu ilginç bir konu. Şimdi kontrol etmek için java kodunu araştırdım. Bulduğuma göre, iki farklı sorun var: Birincisi, uzaktan kapalı soketin yarı çift yönlü veri iletmesine izin veren TCP RFC'nin kendisidir, bu nedenle uzaktan kapalı bir soket hala yarı açık. RFC'ye göre, RST bağlantıyı kapatmaz, açık bir ABORT komutu göndermeniz gerekir; böylece Java yarı kapalı soket üzerinden veri göndermeye izin verir

(Her iki uç noktada da kapanma durumunu okumak için iki yöntem vardır.)

Diğer sorun, uygulamanın bu davranışın isteğe bağlı olduğunu söylemesidir. Java taşınabilir olmaya çabalarken en iyi ortak özelliği uyguladılar. Bir haritanın (OS, yarı çift yönlü uygulanması) korunması bir sorun olurdu, sanırım.


1
RFC 793 ( faqs.org/rfcs/rfc793.html ) Bölüm 3.5 Bir Bağlantıyı Kapatma hakkında konuştuğunuzu varsayalım . Sorunu açıkladığından emin değilim, çünkü her iki taraf da bağlantının zarif bir şekilde kapatılmasını tamamlar ve herhangi bir veri göndermemeleri / almamaları gereken durumlarda sona erer.
Alexander

Bağlı olmak. sokette kaç FIN görüyorsunuz? Ayrıca, platforma özgü bir sorun olabilir: belki windows her FIN'i bir FIN ile yanıtlar ve bağlantı her iki uçta da kapalıdır, ancak diğer işletim sistemleri bu şekilde davranmayabilir ve sorun 2'nin ortaya çıktığı yer burasıdır
Lorenzo Boccaccia

1
Hayır, maalesef durum bu değil. isOutputShutdown ve isInputShutdown, bu "keşif" ile karşılaşıldığında herkesin denediği ilk şeydir, ancak her iki yöntem de yanlış döndürür. Windows XP ve Linux 2.6'da test ettim. Tüm 4 yöntemin dönüş değerleri bir okuma denemesinden sonra bile aynı kalır
Alexander

1
Kayıt için, bu yarı çift yönlü değil. Yarı çift yönlü, bir seferde yalnızca bir tarafın gönderebileceği anlamına gelir; her iki taraf da gönderebilir.
rbp

1
isInputShutdown ve isOutputShutdown , bağlantının yerel ucunu test eder - bunlar, bu Sokette shutdownInput veya shutdownOutput olarak adlandırılıp çağırmadığınızı öğrenmek için yapılan testlerdir. Bağlantının uzak ucu hakkında size hiçbir şey söylemezler.
Mike Dimmick

3

Bu, Java'nın (ve baktığım tüm diğerlerinin) OO soket sınıflarının bir kusuru - seçili sistem çağrısına erişim yok.

C'de doğru cevap:

struct timeval tp;  
fd_set in;  
fd_set out;  
fd_set err;  

FD_ZERO (in);  
FD_ZERO (out);  
FD_ZERO (err);  

FD_SET(socket_handle, err);  

tp.tv_sec = 0; /* or however long you want to wait */  
tp.tv_usec = 0;  
select(socket_handle + 1, in, out, err, &tp);  

if (FD_ISSET(socket_handle, err) {  
   /* handle closed socket */  
}  

İle aynı şeyi yapabilirsiniz getsocketop(... SOL_SOCKET, SO_ERROR, ...).
David Schwartz

1
Hata dosya tanımlayıcı seti, kapalı bağlantıyı göstermez. Lütfen seçme kılavuzunu okuyun: 'hariçfds - Bu set "istisnai koşullar" için izlenir. Pratikte, böyle bir dışsal koşul yaygındır: bir TCP soketinden okumak için bant dışı (OOB) verilerin kullanılabilirliği. ' FIN, OOB verisi değildir.
Jan Wrobel

1
'Select ()' sistem çağrısına erişmek için 'Selector' sınıfını kullanabilirsiniz. Yine de NIO kullanıyor.
Matthieu

1
Karşı tarafın kapattığı bir bağlantının istisnai hiçbir yanı yoktur.
David Schwartz

1
Birçok platformları, dahil Java, do select () sistem çağrısı erişim sağlar.
user207421

2

İşte kötü bir çözüm. SSL kullanın;) ve SSL söküldüğünde yakın bir el sıkışma yapar, böylece soketin kapatıldığına dair bilgilendirilirsiniz (çoğu uygulama uygun bir el sıkışma kopması yapar gibi görünür).


2
Java'da SSL kullanırken soketin kapatıldığı nasıl "bildirilir"?
Dave B

2

Bu davranışın nedeni (Java'ya özgü değildir), TCP yığınından herhangi bir durum bilgisi almamanızdır. Sonuçta, bir soket sadece başka bir dosya tanıtıcısıdır ve gerçekten denemeden ondan okunacak gerçek veri olup olmadığını bulamazsınız ( select(2)orada yardımcı olmaz, yalnızca engellemeden deneyebileceğiniz sinyalini verir).

Daha fazla bilgi için Unix soket SSS bölümüne bakın .


2
REALbasic soketler (Mac OS X ve Linux'ta) BSD soketlerine dayanmaktadır, ancak RB, bağlantı diğer uç tarafından kesildiğinde size güzel bir 102 hatası vermeyi başarır. Bu yüzden orijinal postere katılıyorum, bu mümkün olmalı ve Java (ve Cocoa) bunu sağlamıyor.
Joe Strout

1
@JoeStrout RB bunu yalnızca bazı G / Ç yaptığınızda yapabilir. I / O yapmadan bağlantı durumunu size verecek bir API yoktur. Dönem. Bu bir Java eksikliği değildir. Aslında kasıtlı bir tasarım özelliği olan TCP'de bir 'çevir sesi' eksikliğinden kaynaklanmaktadır.
user207421

select() engellemeden okunabilecek veri veya EOS olup olmadığını gösterir. 'Engellemeden deneyebileceğiniz sinyaller' anlamsızdır. Engellemesiz moddaysanız, her zaman engellemeden deneyebilirsiniz. select()soket alma arabelleğindeki veriler veya bekleyen bir FIN veya yuva gönderme arabelleğindeki boşluk tarafından sürülür.
user207421

@EJP Ne dersiniz getsockopt(SO_ERROR)? Hatta getpeernamesoketin hala bağlı olup olmadığını size söyleyecektir.
David Schwartz

0

Yalnızca yazmalar, paketlerin değiştirilmesini gerektirir, bu da bağlantı kaybının belirlenmesine izin verir. Yaygın bir çözüm, CANLI TUTMA seçeneğini kullanmaktır.


Bir uç noktanın FIN setli bir paket göndererek herhangi bir yük yazmadan zarif bir bağlantı kapatma başlatmasına izin verildiğini düşünüyorum.
Alexander

@Alexander Elbette öyle, ama bu, daha az bağlantı tespit etmekle ilgili olan bu cevapla alakalı değil .
user207421

-3

Yarı açık Java soketleriyle uğraşmaya gelince, isInputShutdown () ve isOutputShutdown () ' a bakmak isteyebilirsiniz .


Hayır. Bu sadece size ne aradığınızı söyler, akranınızın ne aradığını değil.
user207421

Bu ifade için kaynağınızı paylaşmak ister misiniz?
JimmyB

3
Kaynağını bunun tersi için paylaşmak ister misin? Senin ifaden. Kanıtınız varsa, alalım. Hatalı olduğunuzu iddia ediyorum. Deneyi yap ve yanlış olduğumu kanıtla.
user207421

Üç yıl sonra ve deney yok. QED
user207421
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.