远程主机强行关闭了现有连接


158

我正在使用一个商业应用程序,该应用程序会在消息中抛出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流量-–

Answers:


98

这通常意味着远程端关闭了连接(通常通过发送TCP / IP RST数据包)。如果您使用的是第三方应用程序,则可能的原因是:

  • 您正在向应用程序发送格式错误的数据(其中可能包括向HTTP服务器发送HTTPS请求)
  • 客户端和服务器之间的网络链接由于某种原因而断开
  • 您在第三方应用程序中触发了导致其崩溃的错误
  • 第三方应用程序耗尽了系统资源

第一种情况很可能正在发生。

您可以启动Wireshark来查看导线上正在发生的事情,以缩小问题的范围。

没有更多具体信息,这里的任何人都不可能真正为您提供帮助。


2
大。谢谢。关于wireshark的另一件事。它收集了如此多的数据,我该如何过滤掉类似的东西?如果wireshark显示了某些内容,我可能会稍后在此处发布...
peter 2010年

4
您至少应该能够按IP地址和端口号过滤Wireshark转储。之后,查看流的末尾(出问题的地方)并向后工作,直到您发现事情首先被弄乱的地方,这可能是最有用的。取决于所涉及协议的复杂性,它可能真的很容易
甚至

4
是否有项目符号的来源,或者下面玩家的回答只是复制了您的列表?
扎克2014年

7
请注意,“发送格式错误的数据”可能意味着向服务器发送https请求,http反之亦然。
AXMIM

2
就我而言,仅当在本地运行应用程序时调用api时,才出现此异常。在开发,质量保证或生产环境中没有问题。解决办法?在本地使用http而不是https。我们认为这可能与负载均衡器有关。但是我们只是使用https转换更新了dev,qa和prod web.configs。问题解决了。
克肖

82

使用TLS 1.2解决了该错误。
您可以通过以下方式使用TLS 1.2强制您的应用程序(确保在调用服务之前执行它):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

另一个解决方案:
在本地计算机或服务器中启用强加密,以使用TLS1.2,因为默认情况下它被禁用,因此仅使用TLS1.0。
要启用强加密,请在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

这不是代码中的错误。它来自.Net的Socket实现。如果您按如下方式使用EndReceive的重载实现,则不会收到此异常。

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

1
这来自操作系统,最终来自同级。需要进一步说明它是软件错误的说法。
洛恩侯爵,2015年

5
+1。在我的C#程序中,我想知道为什么EndReceive在客户端正常终止时会引发异常。不知道这是设计使然。我觉得在正常的代码流中引发异常的设计很糟糕。感谢上帝的重载方法。
Pavan Manjunath 2015年

2
@MSaudi这正在使用异步调用,请确保您了解代码在处理返回的数据时不会停止。示例使用msdn.microsoft.com/zh-cn/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
@cagatay虽然它提供了一种解决方案,但我从未见过异步方法的价值,在异步方法中,您需要立即了解执行操作后返回的内容,Send然后再执行其他操作。
vapcguy

3
实际上,我发现此方法并非万无一失。它还可能导致OP的错误: stackoverflow.com/questions/17790612/…–
vapcguy

10

解决此常见烦人问题的简单方法:

只需转到您的“ .context.cs”文件(位于 “ * .edmx”文件下的“ .context.tt”下)。

然后,将此行添加到您的构造函数中:

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

希望这会有所帮助。


@Esi放在哪里?而且没有返回类型?
哈利勒·哈拉夫

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仅使用此解决方案有效!只有这个 !谢谢兄弟:)
饶哈马斯

9

有相同的错误。如果使用某些代理发送流量(在我的情况下,是提琴手),实际上是可行的。.NET框架从4.5.2更新到> = 4.6,现在一切正常。实际的请求是:
new WebClient().DownloadData("URL");
例外是:

SocketException:现有连接被远程主机强行关闭


5
这是为我解决问题的一种方式。实际上,它与默认使用的TLS .NET版本有关。4.5.2和更低版本使用TLS 1.0,而4.6和更高版本使用TLS 1.1和1.2更为明智。通过将服务器上的TLS要求降低到1.0也可以证明这一点,该问题也得到了解决。
HotN

4

我有这个异常是因为在entity.In实体中的循环引用看起来像

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]添加到了Parent属性。这就解决了问题。


2

如果在.Net 4.5.2服务中运行

对我来说,这个问题变得更加复杂,因为该调用在.Net 4.5.2服务中运行。我遵循@willmaz的建议,但是遇到了一个新的错误。

在打开日志记录的情况下运行服务时,我查看了与目标站点的握手将启动ok(并发送承载令牌),但是在接下来的步骤中处理Post调用时,它似乎会删除auth令牌,并且站点将回复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是IIS用于与客户端进行http通信的http协议栈。它具有一个称为MinBytesPerSecond的计时器,该计时器负责在其传输速率降至某些kb / sec阈值以下时终止连接。默认情况下,该阈值为设置为240 kb /秒。”

TFS开发团队在此旧博客中描述了此问题,该问题专门涉及IIS,但可能会为您指明正确的方向。它还提到了与此http.sys属性相关的旧错误:链接

如果您使用的是Azure应用程序服务,并且增加缓冲区大小不能解决问题,请尝试同时扩展计算机。将为您分配更多资源,包括连接带宽。


0

我遇到了同样的问题,最终设法解决了。在我的情况下,客户端向其发送请求的端口未绑定SSL证书。因此,我通过将SSL证书绑定到服务器端的端口来解决此问题。一旦完成,该异常就消失了。


-1

每当我在不到10s的时间内未发送或接收数据时,我的CIP协议应用程序中就会发生此错误。

这是由于使用前向打开方法引起的。您可以通过使用其他方法来避免这种情况,或者将更新速率设置为保持正向开放连接的10s以下。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.