Mengapa tidak mungkin, tanpa mencoba I / O, untuk mendeteksi bahwa soket TCP ditutup dengan baik oleh rekan?

93

Sebagai tindak lanjut dari pertanyaan terbaru , saya bertanya-tanya mengapa tidak mungkin di Java, tanpa mencoba membaca / menulis pada soket TCP, untuk mendeteksi bahwa soket telah ditutup dengan baik oleh rekan? Ini tampaknya menjadi kasus terlepas dari apakah seseorang menggunakan pra-NIO Socketatau NIO SocketChannel.

Ketika rekan dengan anggun menutup koneksi TCP, tumpukan TCP di kedua sisi koneksi mengetahui fakta tersebut. Sisi server (yang memulai penghentian) berakhir dalam status FIN_WAIT2, sedangkan sisi klien (yang tidak secara eksplisit menanggapi pematian) berakhir dalam status CLOSE_WAIT. Mengapa tidak ada metode Socketatau SocketChannelyang dapat menanyakan tumpukan TCP untuk melihat apakah koneksi TCP yang mendasari telah diakhiri? Apakah tumpukan TCP tidak memberikan informasi status seperti itu? Ataukah keputusan desain untuk menghindari panggilan yang mahal ke kernel?

Dengan bantuan pengguna yang telah memposting beberapa jawaban untuk pertanyaan ini, saya pikir saya melihat dari mana masalah itu mungkin berasal. Sisi yang tidak secara eksplisit menutup koneksi berakhir dalam status TCP yang CLOSE_WAITberarti bahwa koneksi sedang dalam proses mematikan dan menunggu sisi tersebut mengeluarkan operasinya sendiri CLOSE. Saya kira cukup adil bahwa isConnectedpengembalian truedan isClosedpengembalian false, tetapi mengapa tidak ada yang seperti itu isClosing?

Di bawah ini adalah kelas pengujian yang menggunakan soket pra-NIO. Tetapi hasil yang identik diperoleh dengan menggunakan NIO.

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);
  }
}

Saat klien uji terhubung ke server uji, hasilnya tetap tidak berubah bahkan setelah server memulai pemadaman koneksi:

connected: true, closed: false
connected: true, closed: false
...
Alexander
sumber
Saya rasa saya akan menyebutkan: Protokol SCTP tidak memiliki "masalah" ini. SCTP tidak memiliki status setengah tertutup sebagai TCP, dengan kata lain satu sisi tidak dapat melanjutkan pengiriman data sementara sisi lainnya telah menutup soket pengirimnya. Itu seharusnya membuat segalanya lebih mudah.
Tarnay Kálmán
2
Kami memiliki dua Kotak Surat (Soket) ........................................... ...... Kotak surat saling mengirim surat menggunakan RoyalMail (IP) lupakan TCP ............................. .................... Semua baik-baik saja dan keren, kotak surat dapat mengirim / menerima email satu sama lain (banyak jeda baru-baru ini) mengirim tanpa masalah. ............. Jika satu Kotak Surat tertabrak truk dan gagal .... bagaimana Kotak Surat yang lain tahu? Itu harus diberitahukan oleh Royal Mail, yang pada gilirannya tidak akan mengetahuinya sampai selanjutnya mencoba mengirim / menerima surat dari Kotak Surat yang gagal itu .. ...... erm .....
divinci
Jika Anda tidak akan membaca dari soket atau menulis ke soket, mengapa Anda peduli? Dan jika Anda akan membaca dari soket atau menulis ke soket, mengapa melakukan pemeriksaan ekstra? Apa kasus penggunaannya?
David Schwartz
2
Socket.closebukanlah penutup yang anggun.
pengguna253751
@immibis Ini pasti adalah penutupan yang anggun, kecuali ada data yang belum dibaca di soket penerima buffer atau Anda telah mengacaukan SO_LINGER.
Marquis dari Lorne

Jawaban:

29

Saya telah sering menggunakan Sockets, sebagian besar dengan Selectors, dan meskipun bukan ahli OSI Jaringan, dari pemahaman saya, memanggil shutdownOutput()Socket sebenarnya mengirimkan sesuatu di jaringan (FIN) yang membangunkan Selector saya di sisi lain (perilaku yang sama di C bahasa). Di sini Anda memiliki deteksi : benar-benar mendeteksi operasi baca yang akan gagal saat Anda mencobanya.

Dalam kode yang Anda berikan, menutup soket akan mematikan aliran input dan output, tanpa kemungkinan membaca data yang mungkin tersedia, oleh karena itu kehilangannya. Socket.close()Metode Java melakukan pemutusan hubungan "anggun" (berlawanan dengan apa yang awalnya saya pikirkan) di mana data yang tersisa di aliran keluaran akan dikirim diikuti oleh FIN untuk menandakan penutupannya. FIN akan ACK'd oleh pihak lain, karena setiap paket reguler akan 1 .

Jika Anda perlu menunggu sisi lain menutup soketnya, Anda harus menunggu FIN-nya. Dan untuk mencapai itu, Anda harus mendeteksi Socket.getInputStream().read() < 0, yang berarti Anda tidak boleh menutup soket Anda, karena akan menutupnyaInputStream .

Dari apa yang saya lakukan di C, dan sekarang di Java, mencapai sinkronisasi yang begitu dekat harus dilakukan seperti ini:

  1. Output soket Shutdown (mengirim FIN di ujung lain, ini adalah hal terakhir yang akan dikirim oleh soket ini). Input masih terbuka sehingga Anda dapat read()dan mendeteksi remoteclose()
  2. Baca soket InputStreamsampai kami menerima balasan-FIN dari ujung lain (karena akan mendeteksi FIN, itu akan melalui proses koneksi anggun yang sama). Ini penting pada beberapa OS karena mereka tidak benar-benar menutup soket selama salah satu buffernya masih berisi data. Mereka disebut soket "hantu" dan menggunakan nomor deskriptor di OS (yang mungkin tidak menjadi masalah lagi dengan OS modern)
  3. Tutup soket (dengan memanggil Socket.close()atau menutupnya InputStreamatau OutputStream)

Seperti yang ditunjukkan dalam cuplikan Java berikut:

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
}

Tentu saja kedua belah pihak harus menggunakan cara yang sama untuk menutup, atau bagian pengirim mungkin selalu mengirimkan data yang cukup untuk membuat whileloop tetap sibuk (misalnya jika bagian pengirim hanya mengirim data dan tidak pernah membaca untuk mendeteksi pemutusan koneksi. Yang kikuk, tetapi Anda mungkin tidak memiliki kendali atas hal itu).

Seperti yang ditunjukkan @WarrenDew dalam komentarnya, membuang data dalam program (lapisan aplikasi) menyebabkan pemutusan sambungan yang tidak anggun di lapisan aplikasi: meskipun semua data diterima di lapisan TCP ( whileloop), data tersebut dibuang.

1 : Dari " Jaringan Fundamental di Java ": lihat gbr. 3.3 hal.45, dan keseluruhan §3.7, hal 43-48

Matthieu
sumber
Java memang melakukan penutupan yang anggun. Itu tidak 'brutal'.
Marquis dari Lorne
2
@EJP, "pemutusan anggun" adalah pertukaran khusus yang terjadi pada tingkat TCP, di mana Klien harus memberi sinyal keinginannya untuk memutuskan sambungan ke Server, yang, pada gilirannya, mengirimkan data yang tersisa sebelum menutup sisinya. Bagian "kirim data yang tersisa" harus ditangani oleh program (meskipun orang tidak akan sering mengirim apa pun). Panggilan socket.close()itu "brutal" dengan cara yang tidak menghormati sinyal Klien / Server ini. Server akan diberi tahu tentang pemutusan Klien hanya jika buffer keluaran soketnya sendiri penuh (karena tidak ada data yang diakses oleh sisi lain, yang ditutup).
Matthieu
Lihat MSDN untuk informasi lebih lanjut.
Matthieu
1
@Matthieu Jika aplikasi Anda tidak membaca semua data yang tersedia, itu mungkin tidak dapat dilacak pada lapisan aplikasi, tetapi pada lapisan transport TCP, data tersebut masih diterima dan koneksi dihentikan dengan baik. Hal yang sama berlaku jika aplikasi Anda membaca semua data yang keluar dari aliran input dan hanya membuangnya.
Warren Dew
2
@LeonidUsov Itu tidak benar. Java read()mengembalikan -1 di akhir aliran, dan terus melakukannya berapa kali pun Anda menyebutnya. AC read()atau recv()mengembalikan nol pada akhir aliran, dan terus melakukannya berapa kali pun Anda menyebutnya.
Marquis dari Lorne
18

Saya pikir ini lebih merupakan pertanyaan pemrograman soket. Java hanya mengikuti tradisi pemrograman soket.

Dari Wikipedia :

TCP menyediakan pengiriman aliran byte yang andal dan teratur dari satu program di satu komputer ke program lain di komputer lain.

Setelah jabat tangan selesai, TCP tidak membuat perbedaan apa pun antara dua titik akhir (klien dan server). Istilah "klien" dan "server" sebagian besar ditujukan untuk kenyamanan. Jadi, "server" dapat mengirim data dan "klien" dapat mengirim beberapa data lain secara bersamaan satu sama lain.

Istilah "Tutup" juga menyesatkan. Yang ada hanya pernyataan FIN, yang artinya "Saya tidak akan mengirimkan barang lagi." Tetapi ini tidak berarti bahwa tidak ada paket dalam penerbangan, atau yang lain tidak bisa bicara lagi. Jika Anda menerapkan snail mail sebagai lapisan data link, atau jika paket Anda menempuh rute yang berbeda, mungkin penerima menerima paket dengan urutan yang salah. TCP tahu cara memperbaikinya untuk Anda.

Juga Anda, sebagai sebuah program, mungkin tidak punya waktu untuk terus memeriksa apa yang ada di buffer. Jadi, sesuai keinginan Anda, Anda dapat memeriksa apa yang ada di buffer. Secara keseluruhan, implementasi soket saat ini tidak terlalu buruk. Jika memang ada isPeerClosed (), itu adalah panggilan ekstra yang harus Anda lakukan setiap kali Anda ingin menelepon read.

Eugene Yokota
sumber
1
Saya rasa tidak, Anda dapat menguji status dalam kode C pada windows dan linux !!! Java untuk beberapa alasan mungkin tidak mengekspos beberapa hal, seperti alangkah baiknya untuk mengekspos fungsi gotockopt yang ada di windows dan linux. Faktanya, jawaban di bawah ini memiliki beberapa kode linux C untuk sisi linux.
Dean Hiller
Saya tidak berpikir bahwa memiliki metode 'isPeerClosed ()' membuat Anda berkomitmen untuk memanggilnya sebelum setiap upaya membaca. Anda cukup memanggilnya hanya jika Anda benar-benar membutuhkannya. Saya setuju bahwa implementasi soket saat ini tidak terlalu buruk, meskipun mengharuskan Anda untuk menulis ke aliran keluaran jika Anda ingin mengetahui apakah bagian soket yang jauh ditutup atau tidak. Karena jika tidak, Anda harus menangani data tertulis Anda di sisi lain juga, dan itu sama menyenangkannya dengan duduk di paku yang berorientasi vertikal;)
Jan Hruby
1
Ini tidak berarti 'tidak ada lagi paket dalam penerbangan'. FIN diterima setelah ada data dalam penerbangan. Namun yang tidak berarti adalah bahwa peer telah menutup soket untuk input. Anda harus ** mengirim sesuatu * dan mendapatkan 'reset koneksi' untuk mendeteksinya. FIN bisa saja berarti penghentian produksi.
Marquis dari Lorne
11

API soket yang mendasarinya tidak memiliki pemberitahuan seperti itu.

Tumpukan TCP pengiriman tidak akan mengirim bit FIN hingga paket terakhir, jadi mungkin ada banyak data yang di-buffer dari saat aplikasi pengirim secara logis menutup soketnya bahkan sebelum data itu dikirim. Demikian juga, data yang di-buffer karena jaringan lebih cepat daripada aplikasi penerima (saya tidak tahu, mungkin Anda menyampaikannya melalui koneksi yang lebih lambat) dapat menjadi signifikan bagi penerima dan Anda tidak ingin aplikasi penerima membuangnya. hanya karena bit FIN telah diterima oleh stack.

Mike Dimmick
sumber
Dalam contoh pengujian saya (mungkin saya harus memberikannya di sini ...) tidak ada data yang dikirim / diterima melalui koneksi dengan sengaja. Jadi, saya cukup yakin tumpukan menerima FIN (anggun) atau RST (dalam beberapa skenario tidak anggun). Ini juga dikonfirmasi oleh netstat.
Alexander
1
Tentu - jika tidak ada yang di-buffer maka FIN akan segera dikirim, pada paket yang kosong (tidak ada payload). Namun, setelah FIN, tidak ada lagi paket data yang dikirim oleh ujung koneksi itu (masih akan ACK apa pun yang dikirim ke sana).
Mike Dimmick
1
Apa yang terjadi adalah bahwa sisi koneksi berakhir di <code> CLOSE_WAIT </code> dan <code> FIN_WAIT_2 </code> dan dalam keadaan ini <code> isConcected () </code> dan <code> isClosed () </code> masih tidak melihat bahwa koneksi telah diakhiri.
Alexander
Terima kasih atas saran Anda! Saya rasa saya memahami masalahnya dengan lebih baik sekarang. Saya membuat pertanyaan lebih spesifik (lihat paragraf ketiga): mengapa tidak ada "Socket.isClosing" untuk menguji koneksi setengah tertutup?
Alexander
8

Karena sejauh ini tidak ada jawaban yang sepenuhnya menjawab pertanyaan, saya meringkas pemahaman saya saat ini tentang masalah tersebut.

Ketika koneksi TCP dibuat dan satu peer memanggil close()atau shutdownOutput()pada soketnya, soket di sisi lain dari koneksi beralih ke CLOSE_WAITstatus. Pada prinsipnya, dimungkinkan untuk mengetahui dari tumpukan TCP apakah soket dalam CLOSE_WAITkeadaan tanpa panggilan read/recv(misalnya, getsockopt()di Linux: http://www.developerweb.net/forum/showthread.php?t=4395 ), tetapi itu tidak portabel.

SocketKelas Java tampaknya dirancang untuk menyediakan abstraksi yang sebanding dengan soket TCP TCP, mungkin karena ini adalah tingkat abstraksi yang biasa digunakan orang saat memprogram aplikasi TCP / IP. Soket BSD adalah soket pendukung generalisasi selain hanya soket INET (mis., TCP), jadi soket ini tidak menyediakan cara portabel untuk mengetahui status TCP soket.

Tidak ada metode seperti itu isCloseWait()karena orang yang terbiasa memprogram aplikasi TCP pada tingkat abstraksi yang ditawarkan oleh soket BSD tidak mengharapkan Java menyediakan metode tambahan.

Alexander
sumber
3
Java juga tidak dapat menyediakan metode tambahan apa pun, secara portabel. Mungkin mereka bisa membuat metode isCloseWait () yang akan mengembalikan false jika platform tidak mendukungnya, tetapi berapa banyak programmer yang akan digigit oleh gotcha itu jika mereka hanya menguji pada platform yang didukung?
ephemient
1
sepertinya itu bisa dibawa-bawa bagi saya ... windows memiliki msdn.microsoft.com/en-us/library/windows/desktop/… dan linux ini pubs.opengroup.org/onlinepubs/009695399/functions/…
Dean Hiller
1
Ini bukan karena programmer terbiasa; antarmuka soket itulah yang berguna bagi pemrogram. Perlu diingat bahwa abstraksi soket digunakan lebih dari sekadar protokol TCP.
Warren Dew
Tidak ada metode seperti ini di Java isCloseWait()karena tidak didukung di semua platform.
Marquis dari Lorne
Protokol ident (RFC 1413) memungkinkan server untuk menjaga koneksi tetap terbuka setelah mengirim respons, atau menutupnya tanpa mengirim data lagi. Klien identitas Java mungkin memilih untuk tetap membuka koneksi untuk menghindari jabat tangan 3-arah pada pencarian berikutnya, tetapi bagaimana ia mengetahui bahwa koneksi masih terbuka? Haruskah itu mencoba, menanggapi kesalahan apa pun dengan membuka kembali koneksi? Atau apakah itu kesalahan desain protokol?
david
7

Mendeteksi apakah sisi jarak jauh dari koneksi soket (TCP) telah ditutup dapat dilakukan dengan metode java.net.Socket.sendUrgentData (int), dan menangkap IOException yang dilemparkannya jika sisi jarak jauh tidak aktif. Ini telah diuji antara Java-Java, dan Java-C.

Ini untuk menghindari masalah merancang protokol komunikasi untuk menggunakan semacam mekanisme ping. Dengan menonaktifkan OOBInline pada soket (setOOBInline (false), setiap data OOB yang diterima akan dibuang secara diam-diam, tetapi data OOB masih dapat dikirim. Jika sisi jarak jauh ditutup, reset koneksi akan dicoba, gagal, dan menyebabkan beberapa IOException dilemparkan .

Jika Anda benar-benar menggunakan data OOB dalam protokol Anda, maka jarak tempuh Anda mungkin berbeda.

Paman Per
sumber
4

tumpukan Java IO pasti mengirim FIN saat ia dihancurkan saat pembongkaran tiba-tiba. Tidak masuk akal jika Anda tidak dapat mendeteksi ini, karena sebagian besar klien hanya mengirim FIN jika mereka mematikan koneksi.

... alasan lain saya benar-benar mulai membenci kelas NIO Java. Sepertinya semuanya sedikit setengah-setengah.


sumber
1
juga, tampaknya saya hanya mendapatkan dan end-of-stream pada read (-1 return) ketika FIN hadir. Jadi ini adalah satu-satunya cara yang dapat saya lihat untuk mendeteksi penghentian di sisi baca.
3
Anda bisa mendeteksinya. Anda mendapatkan EOS saat membaca. Dan Java tidak mengirim FIN. TCP melakukan itu. Java tidak mengimplementasikan TCP / IP, ia hanya menggunakan implementasi platform.
Marquis dari Lorne
4

Itu topik yang menarik. Saya baru saja menggali kode java untuk memeriksa. Dari temuan saya, ada dua masalah yang berbeda: yang pertama adalah TCP RFC itu sendiri, yang memungkinkan soket yang tertutup dari jarak jauh untuk mengirimkan data dalam setengah dupleks, sehingga soket yang ditutup dari jarak jauh masih setengah terbuka. Sesuai RFC, RST tidak menutup koneksi, Anda perlu mengirim perintah ABORT eksplisit; jadi Java memungkinkan pengiriman data melalui setengah soket tertutup

(Ada dua metode untuk membaca status tutup di kedua titik akhir.)

Masalah lainnya adalah implementasi mengatakan bahwa perilaku ini opsional. Karena Java berusaha untuk menjadi portabel, mereka menerapkan fitur umum terbaik. Mempertahankan peta (OS, implementasi half duplex) akan menjadi masalah, saya kira.

Lorenzo Boccaccia
sumber
1
Saya kira Anda sedang berbicara tentang RFC 793 ( faqs.org/rfcs/rfc793.html ) Bagian 3.5 Menutup Sambungan. Saya tidak yakin itu menjelaskan masalahnya, karena kedua belah pihak menyelesaikan pematian koneksi yang anggun dan berakhir di negara bagian di mana mereka tidak boleh mengirim / menerima data apa pun.
Alexander
Tergantung. berapa banyak FIN yang Anda lihat di soket? Juga, bisa menjadi masalah khusus platform: mungkin windows membalas setiap FIN dengan FIN dan koneksi ditutup di kedua ujungnya, tetapi sistem operasi lain mungkin tidak berperilaku seperti ini, dan di sinilah masalah 2 muncul
Lorenzo Boccaccia
1
Tidak, sayangnya bukan itu masalahnya. isOutputShutdown dan isInputShutdown adalah hal pertama yang dicoba semua orang ketika dihadapkan dengan "penemuan" ini, tetapi kedua metode mengembalikan false. Saya baru saja mengujinya di Windows XP dan Linux 2.6. Nilai kembalian dari semua 4 metode tetap sama bahkan setelah percobaan pembacaan
Alexander
1
Sebagai catatan, ini bukan half-duplex. Half-duplex berarti hanya satu sisi yang dapat mengirim setiap saat; kedua belah pihak masih bisa mengirim.
rbp
1
isInputShutdown dan isOutputShutdown menguji lokal akhir koneksi - mereka tes untuk mengetahui apakah Anda sudah menelepon shutdownInput atau shutdownOutput pada Socket ini. Mereka tidak memberi tahu Anda apa pun tentang ujung sambungan yang jauh.
Mike Dimmick
3

Ini adalah cacat dari kelas soket OO Java (dan semua yang lain yang pernah saya lihat) - tidak ada akses ke panggilan sistem yang dipilih.

Jawaban yang benar di C:

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 */  
}  
Joshua
sumber
Anda bisa melakukan hal yang sama dengan getsocketop(... SOL_SOCKET, SO_ERROR, ...).
David Schwartz
1
Kumpulan deskriptor file kesalahan tidak akan menunjukkan koneksi tertutup. Silakan baca manual pilihan: 'kecualifds - Set ini diamati untuk "kondisi luar biasa". Dalam praktiknya, hanya satu kondisi ekskesi yang umum: ketersediaan data out-of-band (OOB) untuk membaca dari soket TCP. ' FIN bukanlah data OOB.
Jan Wrobel
1
Anda dapat menggunakan kelas 'Selector' untuk mengakses syscall 'select ()'. Ia menggunakan NIO sekalipun.
Matthieu
1
Tidak ada yang luar biasa tentang koneksi yang telah dimatikan oleh pihak lain.
David Schwartz
1
Banyak platform, termasuk Jawa, lakukan menyediakan akses ke pilih system call ().
Marquis dari Lorne
2

Berikut ini solusi yang payah. Gunakan SSL;) dan SSL melakukan jabat tangan dekat saat pembongkaran sehingga Anda diberi tahu tentang soket yang ditutup (sebagian besar penerapan tampaknya melakukan jabat tangan yang tepat).

Dean Hiller
sumber
2
Bagaimana seseorang mendapatkan "pemberitahuan" dari soket yang ditutup saat menggunakan SSL di java?
Dave B
2

Alasan untuk perilaku ini (yang bukan khusus Java) adalah kenyataan bahwa Anda tidak mendapatkan informasi status apa pun dari tumpukan TCP. Bagaimanapun, soket hanyalah pegangan file lain dan Anda tidak dapat mengetahui apakah ada data aktual untuk dibaca darinya tanpa benar-benar mencoba ( select(2)tidak akan membantu di sana, itu hanya memberi sinyal bahwa Anda dapat mencoba tanpa memblokir).

Untuk informasi lebih lanjut, lihat FAQ soket Unix .

WMR
sumber
2
Soket REALbasic (pada Mac OS X dan Linux) didasarkan pada soket BSD, namun RB berhasil memberi Anda kesalahan 102 ketika koneksi terputus. Jadi saya setuju dengan poster aslinya, ini harus mungkin dan payah karena Java (dan Cocoa) tidak menyediakannya.
Joe Strout
1
@JoeStrout RB hanya dapat melakukannya jika Anda melakukan I / O. Tidak ada API yang akan memberi Anda status koneksi tanpa melakukan I / O. Titik. Ini bukan kekurangan Java. Hal ini sebenarnya karena kurangnya 'nada panggil' di TCP, yang merupakan fitur desain yang disengaja.
Marquis dari Lorne
select() memberi tahu Anda apakah ada data atau EOS yang tersedia untuk dibaca tanpa pemblokiran. 'Sinyal yang dapat Anda coba tanpa memblokir' tidak ada artinya. Jika Anda berada dalam mode non-pemblokiran, Anda selalu dapat mencoba tanpa memblokir. select()didorong oleh data di soket yang menerima buffer atau FIN yang tertunda atau ruang di buffer pengiriman soket.
Marquis dari Lorne
@EJP Bagaimana getsockopt(SO_ERROR)? Bahkan, getpeernameakan memberi tahu Anda jika soket masih terhubung.
David Schwartz
0

Hanya menulis yang mengharuskan paket dipertukarkan yang memungkinkan hilangnya koneksi untuk ditentukan. Solusi yang umum digunakan adalah dengan menggunakan opsi KEEP ALIVE.

sinar
sumber
Saya pikir titik akhir diizinkan untuk memulai penghentian koneksi yang anggun dengan mengirim paket dengan set FIN, tanpa menulis muatan apa pun.
Alexander
@Alexander Tentu saja, tetapi itu tidak relevan dengan jawaban ini, yaitu tentang mendeteksi lebih sedikit koneksi.
Marquis dari Lorne
-3

Ketika berurusan dengan soket Java setengah terbuka, orang mungkin ingin melihat isInputShutdown () dan isOutputShutdown () .

JimmyB
sumber
Tidak. Itu hanya memberitahu Anda apa yang Anda panggil, bukan apa yang disebut rekannya.
Marquis dari Lorne
Mau berbagi sumber pernyataan itu?
JimmyB
3
Mau berbagi sumber yang sebaliknya? Itu pernyataanmu. Jika Anda memiliki bukti, mari kita miliki. Saya menegaskan bahwa Anda tidak benar. Lakukan percobaan dan buktikan bahwa saya salah.
Marquis dari Lorne
Tiga tahun kemudian dan tidak ada percobaan. QED
Marquis dari Lorne