การเชื่อมต่อที่มีอยู่ถูกบังคับให้ปิดโดยโฮสต์ระยะไกล


159

ฉันกำลังทำงานกับแอพพลิเคชั่นทางการค้าที่ใช้ SocketException พร้อมข้อความ

การเชื่อมต่อที่มีอยู่ถูกบังคับให้ปิดโดยโฮสต์ระยะไกล

สิ่งนี้เกิดขึ้นกับการเชื่อมต่อซ็อกเก็ตระหว่างไคลเอนต์และเซิร์ฟเวอร์ การเชื่อมต่อยังมีชีวิตอยู่และดีและมีการถ่ายโอนข้อมูลจำนวนมาก แต่ก็จะถูกตัดการเชื่อมต่อออกจากที่ใดที่หนึ่ง

มีใครเห็นสิ่งนี้มาก่อนหรือไม่ สาเหตุอาจเกิดจากอะไร ฉันสามารถเดาสาเหตุบางอย่างได้ แต่ก็มีวิธีเพิ่มรหัสนี้ลงไปอีกไหมเพื่อหาสาเหตุที่เป็นไปได้

ความคิดเห็น / ความคิดใด ๆ ยินดีต้อนรับ

... ใหม่ล่าสุด ...

ฉันมีการบันทึกจากการติดตาม. 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

จากส่วนอื่น ๆ ของการบันทึกฉันได้เห็นความจริงที่ระบุว่า '0 # 0' หมายถึงการส่งแพ็กเก็ตที่มีความยาว 0 ไบต์ แต่นั่นหมายความว่าอย่างไร

ความเป็นไปได้อย่างหนึ่งอย่างใดอย่างหนึ่งเกิดขึ้นและฉันไม่แน่ใจ

1) การเชื่อมต่อถูกปิด แต่ข้อมูลถูกเขียนลงในซ็อกเก็ตดังนั้นการสร้างข้อยกเว้นข้างต้น 0 # 0 นั้นหมายความว่าไม่มีสิ่งใดถูกส่งเนื่องจากซ็อกเก็ตปิดอยู่แล้ว

2) การเชื่อมต่อยังคงเปิดอยู่และแพ็คเก็ตของศูนย์ไบต์จะถูกส่ง (เช่นรหัสมีข้อผิดพลาด) และ 0 # 0 หมายความว่าแพ็คเก็ตของศูนย์ไบต์พยายามที่จะส่ง

คุณคิดยังไง มันอาจจะสรุปไม่ได้ว่าฉันเดา แต่บางทีคนอื่นเห็นสิ่งนี้?


เพียงแค่อัปเดต ดูเหมือนว่า wireshark จะไม่ตัดมันในกรณีนี้เนื่องจากการตั้งค่าเครือข่ายของเรา แต่ฉันหวังว่าจะลองสิ่งนี้blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspxซึ่งกำลังติดตามการใช้. NET ซึ่งควรสร้างไฟล์บันทึกบางไฟล์ ฉันจะให้คุณโพสต์ ...
เตอร์

1
comcast เป็นที่รู้จักกันในการส่งแพ็คเก็ต "ศูนย์" ปลอมแปลงด้วย id ปลอมไปยุ่งกับปริมาณข้อมูล p2p ---

คำตอบ:


98

โดยทั่วไปหมายความว่าด้านระยะไกลปิดการเชื่อมต่อ (โดยปกติจะส่งRSTแพ็คเก็ตTCP / IP ) หากคุณกำลังทำงานกับแอปพลิเคชันบุคคลที่สามสาเหตุที่เป็นไปได้คือ:

  • คุณกำลังส่งข้อมูลที่มีรูปแบบไม่ถูกต้องไปยังแอปพลิเคชัน (ซึ่งอาจรวมถึงการส่งคำขอ HTTPS ไปยังเซิร์ฟเวอร์ HTTP)
  • ลิงก์เครือข่ายระหว่างไคลเอนต์และเซิร์ฟเวอร์กำลังปิดตัวลงด้วยเหตุผลบางประการ
  • คุณได้เรียกจุดบกพร่องในแอปพลิเคชันบุคคลที่สามที่ทำให้เกิดข้อผิดพลาด
  • แอปพลิเคชันบุคคลที่สามหมดทรัพยากรระบบ

เป็นไปได้ว่ากรณีแรกคือสิ่งที่เกิดขึ้น

คุณสามารถยิงWiresharkเพื่อดูว่าเกิดอะไรขึ้นบนเส้นลวดเพื่อ จำกัด ปัญหาให้แคบลง

หากไม่มีข้อมูลที่เฉพาะเจาะจงมากขึ้นมันไม่น่าเป็นไปได้ที่ทุกคนที่นี่จะสามารถช่วยเหลือคุณได้มาก


2
ยิ่งใหญ่ ขอบคุณ สิ่งอื่น ๆ เกี่ยวกับ wireshark มันรวบรวมข้อมูลมากมายฉันจะกรองบางอย่างเช่นนี้ได้อย่างไร หากการแสดง Wireshark บางสิ่งบางอย่างผมอาจจะโพสต์ไว้ที่นี่ในภายหลัง ...
ปีเตอร์

4
คุณควรจะกรองการถ่ายโอนข้อมูล Wireshark ตามที่อยู่ IP และหมายเลขพอร์ตอย่างน้อยที่สุด หลังจากนั้นอาจเป็นประโยชน์มากที่สุดในการดูจุดสิ้นสุดของสตรีม (ซึ่งมีบางอย่างผิดปกติ) และทำงานย้อนกลับจนกว่าคุณจะสามารถมองเห็นจุดที่สิ่งต่าง ๆ เกิดขึ้นก่อน ทั้งนี้ขึ้นอยู่กับความซับซ้อนของโปรโตคอลที่เกี่ยวข้องก็สามารถเป็นเรื่องง่ายที่จะเป็นไปไม่ได้เกือบ ...
RarrRarrRarr

4
มีแหล่งที่มาสำหรับรายการสัญลักษณ์แสดงหัวข้อย่อยหรือคำตอบของนักเล่นเกมด้านล่างเพียงแค่คัดลอกรายการของคุณ?
Zack

7
โปรดทราบว่า "การส่งข้อมูลที่มีรูปแบบไม่ถูกต้อง" อาจหมายถึงการส่งhttpsคำขอไปยังhttpเซิร์ฟเวอร์และในทางกลับกัน
AXMIM

2
ในกรณีของฉันฉันได้รับข้อยกเว้นนี้เฉพาะเมื่อเรียก api เมื่อเรียกใช้แอปในเครื่อง ไม่มีปัญหาในสภาพแวดล้อม dev, qa หรือ prod การแก้ไข? ใช้ http แทน https ภายในเครื่อง เราคิดว่าอาจเกี่ยวข้องกับโหลดบาลานเซอร์ แต่เราเพิ่งอัปเดต dev, qa และ prod web.configs ด้วยการแปลงสำหรับ https แก้ไขปัญหา.
Kershaw

82

การใช้ TLS 1.2 แก้ไขข้อผิดพลาดนี้
คุณสามารถบังคับให้แอปพลิเคชันของคุณใช้ TLS 1.2 ด้วยสิ่งนี้ (ตรวจสอบให้แน่ใจว่าได้ดำเนินการก่อนที่จะเรียกใช้บริการของคุณ)

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

โซลูชันอื่น:
เปิดใช้งานการเข้ารหัสที่รัดกุมในเครื่องหรือเซิร์ฟเวอร์ของคุณเพื่อใช้ TLS1.2 เนื่องจากโดยค่าเริ่มต้นจะถูกปิดใช้งานดังนั้นจะใช้ TLS1.0 เท่านั้น
ในการเปิดใช้งานการเข้ารหัสที่รัดกุมดำเนินการ commande เหล่านี้ใน PowerShell ด้วยสิทธิ์ผู้ดูแลระบบ:

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 

คุณต้องรีบูตคอมพิวเตอร์เพื่อให้การเปลี่ยนแปลงเหล่านี้มีผล


1
คุณสามารถเพิ่มค่าหลายค่าพร้อมกันเพื่อรองรับหลายโปรโตคอล ดังนั้นเพื่อรองรับทุกอย่างตั้งแต่ SSL3 ถึง TLS1.2 ให้ตั้งค่า SecurityProtocol = (SecurityProtocolType) 4080
ลูกคิด

29

นี่ไม่ใช่ข้อผิดพลาดในรหัสของคุณ มันมาจากการใช้ Socket ของ. Net หากคุณใช้การใช้งานมากเกินไปของ EndReceive ด้านล่างคุณจะไม่ได้รับข้อยกเว้นนี้

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }

1
นี่มาจากระบบปฏิบัติการและในที่สุดก็มาจากเพื่อน จำเป็นต้องมีคำอธิบายเพิ่มเติมในข้อกล่าวหาว่าเป็นข้อบกพร่องของซอฟต์แวร์
มาร์ควิสแห่ง Lorne

5
+1 ในโปรแกรม C # ของฉันฉันกำลังตีหัวของฉันเป็นสาเหตุที่EndReceiveทำให้เกิดข้อยกเว้นเมื่อมีการเลิกจ้างลูกค้าที่สง่างาม ไม่ทราบว่าเป็นเพราะการออกแบบ ฉันรู้สึกว่าการออกแบบไม่ดีในการจัดการข้อยกเว้นในโค้ดปกติ ขอบคุณพระเจ้าสำหรับวิธีที่มากเกินไป
Pavan Manjunath

2
@MSaudi สิ่งนี้กำลังใช้การเรียกแบบอะซิงโครนัสให้แน่ใจว่าคุณเข้าใจรหัสของคุณจะไม่หยุดในขณะที่กำลังประมวลผลข้อมูลที่ส่งคืน ตัวอย่างการใช้msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx โดยทั่วไปคุณจะต้องมีStateObjectคลาสด้วยpublic byte[] buffer = new byte[1024], public Socket socket;และเรียกใช้ฟังก์ชันที่เรียกว่าReceive(Socket s)ซึ่งทำStateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); และในvoid ReceiveCallback(IAsyncResult ar)คุณเรียกรหัสนั้นข้างต้น
vapcguy

2
@catatay ในขณะที่มันมีทางออกฉันไม่เคยเห็นคุณค่าในวิธีการแบบอะซิงโครนัสที่คุณจำเป็นต้องรู้ทันทีว่าสิ่งที่จะกลับมาหลังจากที่คุณทำของคุณSendก่อนที่คุณจะทำอะไรอย่างอื่น
vapcguy

3
จริงๆแล้วฉันพบว่าวิธีนี้ไม่สามารถจะเข้าใจผิดได้ นอกจากนี้ยังสามารถทำให้เกิดข้อผิดพลาดของ OP: stackoverflow.com/questions/17790612/ …
vapcguy

10

วิธีง่ายๆสำหรับปัญหาที่น่ารำคาญนี้:

เพียงไปที่ไฟล์ ".context.cs" (อยู่ใต้ " .context.tt" ซึ่งอยู่ใต้ไฟล์ "* .edmx" ของคุณ)

จากนั้นเพิ่มบรรทัดนี้ลงในตัวสร้างของคุณ:

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

หวังว่านี่จะเป็นประโยชน์


@Esi จะวางที่ไหน และไม่มีประเภทผลตอบแทน?
Khalil Khalaf

2
@FirstStep: เพราะนี่คือตัวสร้าง
Nikhil Agrawal

3
สิ่งนี้จะช่วยให้ผู้ที่ใช้ Entity Framework ที่ประสบปัญหาไม่ใช่ผู้ที่กำลังทำการsocket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);อ่านไบต์ที่ส่งคืนซึ่งเป็นปัญหาของ OP อย่างง่าย
vapcguy

ถ้าใช้ENTITY FRAMEWORKเฉพาะวิธีนี้ใช้งานได้ !!! แค่นี้ !
Thanks

9

มีข้อผิดพลาดเดียวกัน ใช้งานได้จริงในกรณีที่ปริมาณการใช้ข้อมูลถูกส่งโดยใช้พร็อกซีบางส่วน (พู้ทำเล่นในกรณีของฉัน) อัปเดตกรอบงาน. NET จาก 4.5.2 เป็น> = 4.6 และตอนนี้ทุกอย่างทำงานได้ดี คำขอที่แท้จริงคือ:
new WebClient().DownloadData("URL");
ข้อยกเว้นคือ:

SocketException: การเชื่อมต่อที่มีอยู่ถูกบังคับให้ปิดโดยโฮสต์ระยะไกล


5
นี่เป็นวิธีหนึ่งในการแก้ปัญหาให้ฉัน จริง ๆ แล้วมันเกี่ยวข้องกับ TLS .NET เวอร์ชันที่ใช้โดยค่าเริ่มต้น 4.5.2 และ TLS ที่ใช้ต่ำกว่า 1.0 ในขณะที่ 4.6 และสูงกว่านั้นฉลาดกว่าเกี่ยวกับการอนุญาต 1.1 และ 1.2 สิ่งนี้สามารถพิสูจน์ได้ด้วยการวางข้อกำหนด TLS บนเซิร์ฟเวอร์ลงที่ 1.0 ซึ่งแก้ไขปัญหาเช่นกัน
HotN

4

ฉันได้รับข้อยกเว้นนี้เนื่องจากการอ้างอิงแบบวงกลมในเอนทิตีในเอนทิตีที่มีลักษณะเหมือน

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

ฉันเพิ่ม [IgnoreDataMemberAttribute] ให้กับคุณสมบัติหลัก และนั่นก็แก้ปัญหาได้


2

ถ้าใช้บริการ A .Net 4.5.2

สำหรับฉันแล้วปัญหานี้เกิดขึ้นเนื่องจากการโทรทำงานในบริการ. Net 4.5.2 ฉันทำตามคำแนะนำ @willmaz แต่มีข้อผิดพลาดใหม่

ในการเรียกใช้บริการโดยเปิดการบันทึกฉันดูการจับมือกับไซต์เป้าหมายจะเริ่มต้นตกลง (และส่งโทเค็นผู้ถือ) แต่ในขั้นตอนต่อไปนี้เพื่อประมวลผลการโทรโพสต์ดูเหมือนว่าจะลดโทเค็นรับรองความถูกต้องแล้ว Unauthorizedตอบกลับด้วย

มันกลับกลายเป็นว่าข้อมูลประจำตัวของกลุ่มการบริการไม่มีสิทธิ์ในการเปลี่ยน TLS (?) และเมื่อฉันใส่บัญชีผู้ดูแลระบบภายในเครื่องของฉันลงในกลุ่มการทำงานทั้งหมดก็ใช้งานได้


2

สำหรับทุกคนที่ได้รับข้อยกเว้นนี้ในขณะที่อ่านข้อมูลจากสตรีมสิ่งนี้อาจช่วยได้ ฉันได้รับข้อยกเว้นนี้เมื่ออ่าน HttpResponseMessage ในลูปแบบนี้

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

หลังจากระยะเวลาหนึ่งฉันพบผู้กระทำผิดคือขนาดบัฟเฟอร์ซึ่งเล็กเกินไปและเล่นได้ไม่ดีกับอินสแตนซ์ Azure ที่อ่อนแอของฉัน สิ่งที่ช่วยได้คือเปลี่ยนรหัสเป็น:

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

CopyTo ()วิธีการมีขนาดบัฟเฟอร์เริ่มต้นของ 81920 บัฟเฟอร์ที่ใหญ่กว่าเร่งกระบวนการและข้อผิดพลาดหยุดทันทีส่วนใหญ่เนื่องจากความเร็วในการดาวน์โหลดโดยรวมเพิ่มขึ้น แต่ทำไมความเร็วในการดาวน์โหลดถึงสำคัญในการป้องกันข้อผิดพลาดนี้?

อาจเป็นไปได้ว่าคุณถูกตัดการเชื่อมต่อจากเซิร์ฟเวอร์เนื่องจากความเร็วในการดาวน์โหลดลดลงต่ำกว่าเกณฑ์ขั้นต่ำที่เซิร์ฟเวอร์กำหนดไว้ให้อนุญาต ตัวอย่างเช่นในกรณีที่แอปพลิเคชันที่คุณดาวน์โหลดไฟล์ถูกโฮสต์อยู่บน IIS อาจเป็นปัญหากับการกำหนดค่า http.sys:

"Http.sys เป็นโพรโทคอล http โพรโทคอลที่ IIS ใช้เพื่อทำการสื่อสาร http กับไคลเอนต์มีตัวจับเวลาที่เรียกว่า MinBytesPerSecond ที่รับผิดชอบฆ่าการเชื่อมต่อถ้าอัตราการถ่ายโอนลดลงต่ำกว่าขีด จำกัด kb / วินาทีบางตัว ตั้งค่าเป็น 240 kb / วินาที "

ปัญหานี้ได้อธิบายไว้ใน blogpost เก่านี้จากทีมพัฒนา TFS และเกี่ยวข้องกับ IIS โดยเฉพาะ แต่อาจนำคุณไปในทิศทางที่ถูกต้อง นอกจากนี้ยังกล่าวถึงข้อบกพร่องเก่า ๆ ที่เกี่ยวข้องกับแอตทริบิวต์ http.sys นี้: ลิงก์

ในกรณีที่คุณใช้บริการแอป Azure และการเพิ่มขนาดบัฟเฟอร์ไม่ได้ช่วยขจัดปัญหาให้ลองปรับขนาดเครื่องของคุณด้วย คุณจะได้รับการจัดสรรทรัพยากรมากขึ้นรวมถึงแบนด์วิดธ์การเชื่อมต่อ


0

ฉันมีปัญหาเดียวกันและจัดการเพื่อแก้ไขในที่สุด ในกรณีของฉันพอร์ตที่ไคลเอนต์ส่งการร้องขอไปไม่มีใบรับรอง SSL ที่เชื่อมโยง ดังนั้นฉันจึงแก้ไขปัญหาโดยผูกใบรับรอง SSL กับพอร์ตที่ฝั่งเซิร์ฟเวอร์ เมื่อเสร็จแล้วข้อยกเว้นนี้ก็หายไป


-1

ข้อผิดพลาดนี้เกิดขึ้นในแอปพลิเคชันของฉันที่มีโปรโตคอล CIP เมื่อใดก็ตามที่ฉันไม่ได้ส่งหรือรับข้อมูลในเวลาน้อยกว่า 10 วินาที

นี่คือสาเหตุมาจากการใช้วิธีการเปิดไปข้างหน้า คุณสามารถหลีกเลี่ยงปัญหานี้ได้ด้วยการทำงานกับวิธีอื่นหรือติดตั้งอัตราการอัพเดทน้อยกว่า 10 วินาทีที่รักษาการเชื่อมต่อไปข้างหน้าของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.