Koneksi yang ada ditutup secara paksa oleh host jarak jauh

159

Saya bekerja dengan aplikasi komersial yang melempar SocketException dengan pesan,

Koneksi yang ada ditutup secara paksa oleh host jarak jauh

Ini terjadi dengan koneksi soket antara klien dan server. Sambungannya hidup dan baik, dan banyak data yang ditransfer, tetapi kemudian terputus entah dari mana.

Adakah yang pernah melihat ini sebelumnya? Apa penyebabnya? Saya bisa menebak beberapa penyebab, tetapi juga adakah cara untuk menambahkan lebih banyak ke dalam kode ini untuk mengetahui apa penyebabnya?

Setiap komentar / ide dipersilakan.

... Terbaru ...

Saya memiliki beberapa pencatatan dari beberapa pelacakan .NET,

System.Net.Sockets Verbose: 0 : [8188] Socket#30180123::Send() DateTime=2010-04-07T20:49:48.6317500Z

System.Net.Sockets Error: 0 : [8188] Exception in the Socket#30180123::Send - An existing connection was forcibly closed by the remote host DateTime=2010-04-07T20:49:48.6317500Z 

System.Net.Sockets Verbose: 0 : [8188] Exiting Socket#30180123::Send() -> 0#0

Berdasarkan bagian lain dari logging saya telah melihat fakta bahwa ia mengatakan '0 # 0' berarti paket panjang 0 byte sedang dikirim. Tapi, apa arti sebenarnya?

Salah satu dari dua kemungkinan terjadi, dan saya tidak yakin yang mana,

1) Koneksi sedang ditutup, tetapi data kemudian ditulis ke soket, sehingga menciptakan pengecualian di atas. 0 # 0 berarti tidak ada yang dikirim karena soket sudah ditutup.

2) Sambungan masih terbuka, dan paket nol byte sedang dikirim (yaitu kode memiliki bug) dan 0 # 0 berarti bahwa paket nol byte sedang mencoba dikirim.

Menurutmu apa? Mungkin tidak meyakinkan saya kira, tetapi mungkin orang lain telah melihat hal semacam ini?

Peter
sumber
Hanya pembaruan. Tampaknya wireshark tidak akan memotongnya dalam kasus ini karena pengaturan jaringan kami. Tapi mudah-mudahan saya akan mencoba ini, blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx yang melacak menggunakan. NET yang seharusnya menghasilkan beberapa file log. Saya akan membuat Anda tetap diposting ...
peter
1
comcast juga dikenal mengirim paket "nol" yang dipalsukan dengan id palsu untuk mengacaukan lalu lintas P2P

Jawaban:

98

Ini umumnya berarti bahwa sisi jauh menutup koneksi (biasanya dengan mengirim paket TCP / IP RST). Jika Anda bekerja dengan aplikasi pihak ketiga, kemungkinan penyebabnya adalah:

  • Anda mengirim data yang salah ke aplikasi (yang dapat mencakup mengirim permintaan HTTPS ke server HTTP)
  • Tautan jaringan antara klien dan server turun karena beberapa alasan
  • Anda telah memicu bug di aplikasi pihak ketiga yang menyebabkannya mogok
  • Aplikasi pihak ketiga telah kehabisan sumber daya sistem

Kemungkinan kasus pertama adalah apa yang terjadi.

Anda dapat menjalankan Wireshark untuk melihat apa yang terjadi pada kabel untuk mempersempit masalah.

Tanpa informasi yang lebih spesifik, tidak mungkin ada orang di sini yang benar-benar dapat membantu Anda.

RarrRarrRarr
sumber
2
Bagus. Terima kasih. Hal lain tentang wireshark. Ia mengumpulkan begitu banyak data, bagaimana saya bisa menyaring sesuatu seperti ini? Jika wireshark menunjukkan sesuatu, saya mungkin mempostingnya di sini nanti ...
peter
4
Anda harus bisa memfilter pembuangan Wireshark dengan alamat IP dan nomor port, setidaknya. Setelah itu, mungkin paling bermanfaat untuk melihat ujung sungai (di mana terjadi kesalahan) dan bekerja mundur sampai Anda dapat melihat di mana hal-hal pertama menjadi kacau. Bergantung pada kerumitan protokol yang terlibat, bisa sangat mudah untuk hampir tidak mungkin ...
RarrRarrRarr
4
Apakah ada sumber untuk item berpoin, atau apakah jawaban gamer di bawah ini hanya menyalin daftar Anda?
Zack
7
Harap perhatikan bahwa "mengirim data yang cacat" dapat berarti mengirim httpspermintaan ke httpserver dan mungkin sebaliknya.
AXMIM
2
Dalam kasus saya, saya mendapatkan pengecualian ini hanya ketika memanggil api ketika menjalankan aplikasi secara lokal. Tidak ada masalah di lingkungan dev, qa, atau prod. Memperbaiki? Menggunakan http alih-alih https secara lokal. Kami pikir itu mungkin terkait dengan penyeimbang beban. Tapi kami baru saja memperbarui dev, qa, dan prod web.configs kami dengan transformasi untuk https. Masalah terpecahkan.
Kershaw
82

Menggunakan TLS 1.2 menyelesaikan kesalahan ini.
Anda dapat memaksa aplikasi Anda menggunakan TLS 1.2 dengan ini (pastikan untuk menjalankannya sebelum memanggil layanan Anda):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

Solusi lain:
Aktifkan kriptografi yang kuat di mesin atau server lokal Anda untuk menggunakan TLS1.2 karena secara default itu dinonaktifkan sehingga hanya TLS1.0 yang digunakan.
Untuk mengaktifkan kriptografi yang kuat, jalankan perintah ini di PowerShell dengan hak admin:

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

Anda harus me-reboot komputer Anda agar perubahan ini dapat diterapkan.

willmaz
sumber
1
Anda dapat menambahkan beberapa nilai secara bersamaan untuk mendukung banyak protokol. Jadi untuk mendukung semuanya, mulai dari SSL3 hingga TLS1.2, atur SecurityProtocol = (SecurityProtocolType) 4080.
Abacus
29

Ini bukan bug dalam kode Anda. Itu berasal dari implementasi Socket Net. Jika Anda menggunakan implementasi EndReceive yang kelebihan beban seperti di bawah ini, Anda tidak akan mendapatkan pengecualian ini.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }
cagatay
sumber
1
Ini berasal dari sistem operasi, dan akhirnya dari rekan. Penjelasan lebih lanjut diperlukan untuk tuduhan bahwa itu adalah bug perangkat lunak.
Marquis of Lorne
5
+1. Dalam program C # saya, saya membenturkan kepala saya mengapa EndReceivemelemparkan pengecualian ketika ada pemutusan klien yang anggun. Tidak tahu ini dari desain. Saya merasa desain yang buruk untuk membuang pengecualian dalam aliran kode normal. Terima kasih Tuhan atas metode kelebihan beban.
Pavan Manjunath
2
@ MSaudi Ini menggunakan panggilan tidak sinkron, pastikan Anda memahami kode Anda tidak akan berhenti saat sedang memproses data yang sedang dikembalikan. Contoh menggunakan msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx . Pada dasarnya Anda harus memiliki StateObjectkelas dengan public byte[] buffer = new byte[1024], public Socket socket;dan memanggil fungsi yang dipanggil Receive(Socket s), yang tidak StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); dan dalam void ReceiveCallback(IAsyncResult ar)Anda memanggil kode itu, di atas.
vapcguy
2
@catcatay Sementara ia menawarkan solusi, saya tidak pernah melihat nilai dalam metode asinkron di mana Anda harus segera mengetahui apa yang akan kembali setelah Anda melakukan Sendsebelum Anda dapat melakukan hal lain.
vapcguy
3
Sebenarnya saya menemukan bahwa metode ini tidak mudah. Itu juga dapat menyebabkan kesalahan OP: stackoverflow.com/questions/17790612/…
vapcguy
10

Solusi sederhana untuk masalah umum yang menjengkelkan ini:

Buka saja file ".context.cs" Anda (terletak di bawah " .context.tt" yang terletak di bawah file "* .edmx" Anda).

Lalu, tambahkan baris ini ke konstruktor Anda:

public DBEntities() 
        : base("name=DBEntities") 
    { 
        this.Configuration.ProxyCreationEnabled = false; // ADD THIS LINE !
    }

Semoga ini bermanfaat.

ayheber
sumber
@ Esi di mana menaruh ini? dan tidak ada tipe pengembalian ??
Khalil Khalaf
2
@FirstStep: Karena ini adalah konstruktor.
Nikhil Agrawal
3
Ini hanya membantu mereka yang menggunakan Kerangka Entitas yang mengalami masalah, bukan mereka yang melakukan sederhana socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);untuk membaca byte yang dikembalikan, yang merupakan masalah OP.
vapcguy
jika ENTITY FRAMEWORKhanya menggunakan solusi ini berfungsi !!! hanya ini ! terima kasih bro :)
Rao Hammas
9

Punya bug yang sama. Sebenarnya berfungsi jika lalu lintas dikirim menggunakan beberapa proxy (pemain biola dalam kasus saya). Kerangka .NET diperbarui dari 4.5.2 hingga> = 4.6 dan sekarang semuanya berfungsi dengan baik. Permintaan aktual adalah:
new WebClient().DownloadData("URL");
Pengecualian adalah:

SocketException: Koneksi yang ada ditutup secara paksa oleh host jarak jauh

0x49D1
sumber
5
Ini adalah salah satu cara untuk menyelesaikan masalah bagi saya. Ini sebenarnya terkait dengan versi TLS. NET yang digunakan secara default. 4.5.2 dan TLS 1.0 yang lebih rendah digunakan, sementara 4.6 dan lebih besar lebih pintar tentang memungkinkan 1.1 dan 1.2. Ini juga dapat dibuktikan dengan menjatuhkan persyaratan TLS di server ke 1.0, yang memperbaiki masalah ini juga.
HotN
4

Saya mendapatkan pengecualian ini karena referensi melingkar pada entitas. Pada entitas yang terlihat seperti

public class Catalog
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public Catalog Parent { get; set; }
    public ICollection<Catalog> ChildCatalogs { get; set; }
}

Saya menambahkan [IgnoreDataMemberAttribute] ke properti Parent. Dan itu memecahkan masalah.

Bazaleev Nikolay
sumber
2

Jika Berjalan Di Layanan .Net 4.5.2

Bagi saya masalah ini diperparah karena panggilan berjalan di layanan .Net 4.5.2. Saya mengikuti saran @willmaz tetapi mendapat kesalahan baru.

Dalam menjalankan layanan dengan logging dihidupkan, saya melihat jabat tangan dengan situs target akan memulai ok (dan mengirim token pembawa) tetapi pada langkah berikut untuk memproses panggilan Post, tampaknya akan menjatuhkan token auth dan situs akan balas dengan Unauthorized.

Ternyata kredensial kumpulan layanan tidak memiliki hak untuk mengubah TLS (?) Dan ketika saya memasukkan akun admin lokal saya ke kumpulan, semuanya berfungsi.

GamegaMan
sumber
2

Bagi siapa pun yang mendapatkan pengecualian ini saat membaca data dari aliran, ini dapat membantu. Saya mendapatkan pengecualian ini ketika membaca HttpResponseMessage dalam satu lingkaran seperti ini:

using (var remoteStream = await response.Content.ReadAsStreamAsync())
using (var content = File.Create(DownloadPath))
{
    var buffer = new byte[1024];
    int read;

    while ((read = await remoteStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
    {
        await content.WriteAsync(buffer, 0, read);
        await content.FlushAsync();
    }
}

Setelah beberapa waktu saya menemukan pelakunya adalah ukuran buffer, yang terlalu kecil dan tidak cocok dengan contoh Azure saya yang lemah. Yang membantu adalah mengubah kode menjadi:

using (Stream remoteStream = await response.Content.ReadAsStreamAsync())
using (FileStream content = File.Create(DownloadPath))
{
    await remoteStream.CopyToAsync(content);
}

Metode CopyTo () memiliki ukuran buffer default 81920. Semakin besar buffer mempercepat proses dan kesalahan segera berhenti, kemungkinan besar karena keseluruhan kecepatan unduhan meningkat. Tetapi mengapa kecepatan unduh penting untuk mencegah kesalahan ini?

Mungkin saja Anda terputus dari server karena kecepatan unduh turun di bawah ambang batas minimum yang dikonfigurasikan oleh server. Misalnya, jika aplikasi yang Anda unduh file di-host pada IIS, itu bisa menjadi masalah dengan konfigurasi http.sys:

"Http.sys adalah tumpukan protokol http yang digunakan IIS untuk melakukan komunikasi http dengan klien. Ia memiliki timer yang disebut MinBytesPerSecond yang bertanggung jawab untuk mematikan koneksi jika laju transfer turun di bawah ambang kb / detik. Secara default, ambang tersebut adalah setel ke 240 kb / detik. "

Masalahnya dijelaskan dalam blogpost lama ini dari tim pengembangan TFS dan secara khusus menyangkut IIS, tetapi mungkin mengarahkan Anda ke arah yang benar. Itu juga menyebutkan bug lama yang terkait dengan atribut http.sys ini: tautan

Jika Anda menggunakan layanan aplikasi Azure dan meningkatkan ukuran buffer tidak menghilangkan masalah, cobalah untuk meningkatkan mesin Anda juga. Anda akan dialokasikan lebih banyak sumber daya termasuk bandwidth koneksi.

Andrej Lucansky
sumber
0

Saya memiliki masalah yang sama dan akhirnya berhasil menyelesaikannya. Dalam kasus saya, port tempat klien mengirim permintaan tidak memiliki sertifikat SSL yang mengikatnya. Jadi saya memperbaiki masalah dengan mengikat sertifikat SSL ke port di sisi server. Setelah itu selesai, pengecualian ini hilang.

iefgnoix
sumber
-1

Kesalahan ini terjadi pada aplikasi saya dengan protokol CIP setiap kali saya tidak mengirim atau menerima data dalam waktu kurang dari 10 detik.

Ini disebabkan oleh penggunaan metode forward open. Anda dapat menghindari ini dengan bekerja dengan metode lain, atau untuk menginstal tingkat pembaruan kurang dari 10-an yang menjaga koneksi terbuka-depan Anda.

Belekz
sumber