Pertanyaan Mendeteksi sambungan soket yang tidak diharapkan


Ini bukan pertanyaan tentang bagaimana melakukan ini, tetapi pertanyaan tentang apakah itu salah apa yang saya lakukan. Saya pernah membaca bahwa tidak mungkin mendeteksi apakah soket ditutup secara tidak terduga (seperti membunuh proses server / klien, menarik kabel jaringan) sambil menunggu data (BeginReceive), tanpa menggunakan pengatur waktu atau pesan terkirim reguler, dll. Tapi cukup lama saya menggunakan pengaturan berikut untuk melakukan ini, dan sejauh ini selalu berhasil dengan sempurna.

public void OnReceive(IAsyncResult result)
{
    try
    {
        var bytesReceived = this.Socket.EndReceive(result);

        if (bytesReceived <= 0)
        {
            // normal disconnect
            return;
        }

        // ...

        this.Socket.BeginReceive...;
    }
    catch // SocketException
    {
        // abnormal disconnect
    }
}

Sekarang, karena saya sudah membaca itu tidak mudah, saya bertanya-tanya apakah ada yang salah dengan metode saya. Disana? Atau apakah ada perbedaan antara proses pembunuhan dan penarikan kabel dan sejenisnya?


5
2017-07-05 08:13


asal


Jawaban:


Sangat mungkin dan OK untuk melakukan ini. Ide umumnya adalah:

Jika EndReceive mengembalikan apa pun selain nol, Anda memiliki data yang masuk untuk diproses.

Jika EndReceive mengembalikan nol, host jarak jauh telah menutup akhir sambungannya. Itu berarti ia masih dapat menerima data yang Anda kirim jika diprogram untuk melakukannya, tetapi tidak dapat mengirimnya sendiri dalam keadaan apa pun. Biasanya ketika ini terjadi Anda juga akan menutup koneksi Anda sehingga menyelesaikan shutdown yang teratur, tetapi itu tidak wajib.

Jika EndReceive melempar, ada penghentian koneksi yang tidak normal (proses yang terbunuh, pemutusan kabel jaringan, pemadaman listrik, dll).

Beberapa poin yang harus Anda perhatikan:

  1. EndReceive tidak pernah dapat kembali kurang dari nol (tes dalam kode Anda menyesatkan).
  2. Jika melempar itu bisa melempar pengecualian jenis lain selain SocketException.
  3. Jika kembali nol Anda harus berhati-hati untuk berhenti menelepon BeginReceive; jika tidak, Anda akan memulai permainan ping-pong tanpa batas dan tidak berarti BeginReceive dan EndReceive (ini akan ditampilkan dalam penggunaan CPU Anda). Kode Anda sudah melakukan ini, jadi tidak perlu mengubah apa pun.

12
2017-07-05 08:21