C# 远程主机已强制关闭现有连接

C# 远程主机已强制关闭现有连接,c#,.net,networking,sockets,C#,.net,Networking,Sockets,我正在使用一个商业应用程序,它在消息中抛出SocketException 远程主机已强制关闭现有连接 这种情况发生在客户端和服务器之间的套接字连接上。连接是活跃的、良好的,大量的数据正在传输,但是它突然断开了连接 以前有人见过这个吗?原因可能是什么?我可以猜出一些原因,但是有没有办法在代码中添加更多的内容来找出原因 欢迎提出任何意见/想法 。。。最新的 我有一些.NET跟踪记录 System.Net.Sockets Verbose: 0 : [8188] Socket#30180123::Sen

我正在使用一个商业应用程序,它在消息中抛出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字节的数据包。但这到底意味着什么

两种可能性中的一种正在发生,我不确定是哪一种

  • 连接正在关闭,但数据随后被写入套接字,从而产生上述异常。
    0#0
    仅仅意味着由于套接字已关闭,因此未发送任何内容

  • 连接仍处于打开状态,正在发送一个零字节的数据包(即代码有错误),而
    0#0
    表示试图发送一个零字节的数据包


  • 你认为呢?我想这可能是不确定的,但可能其他人看到过这种情况?

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

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

    您可以启动以查看线路上到底发生了什么,从而缩小问题的范围


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

    这不是您代码中的错误。它来自.Net的套接字实现。如果按如下所示使用EndReceive的重载实现,则不会出现此异常

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

    此常见恼人问题的简单解决方案:

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

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

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

    希望这是有帮助的

    我得到这个异常是因为实体中的循环引用。在实体中

    public class Catalog
    {
        public int Id { get; set; }
        public int ParentId { get; set; }
        public Catalog Parent { get; set; }
        public ICollection<Catalog> ChildCatalogs { get; set; }
    }
    
    公共类目录
    {
    公共int Id{get;set;}
    public int ParentId{get;set;}
    公共目录父项{get;set;}
    公共ICollection子目录{get;set;}
    }
    

    我将[IgnoreDataMemberAttribute]添加到父属性。这就解决了问题。

    也有同样的错误。在使用代理发送流量的情况下(在我的情况下是fiddler),实际工作正常。将.NET framework从4.5.2更新为>=4.6,现在一切正常。实际请求是:
    newWebClient()。下载数据(“URL”)
    例外情况是:

    SocketException:现有连接被 远程主机


    每当我在不到10秒内没有发送或接收数据时,使用CIP协议的应用程序就会出现此错误


    这是由于使用正向打开方法造成的。您可以通过使用其他方法来避免这种情况,或者安装更新率低于10秒的设备,以保持前向开放连接

    使用TLS 1.2解决了此错误。
    您可以使用TLS 1.2强制应用程序执行此操作(请确保在调用服务之前执行此操作):

    另一种解决方案:
    在本地计算机或服务器中启用强加密以使用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 
    

    要使这些更改生效,您需要重新启动计算机。

    如果在.Net 4.5.2服务中运行

    对我来说,这个问题更加复杂,因为这个电话是在.NET4.5.2服务中运行的。我遵循了@willmaz的建议,但又犯了一个新错误

    在日志记录打开的情况下运行服务时,我看到与目标站点的握手将启动ok(并发送承载令牌),但在处理Post调用的下一步中,它似乎会丢弃auth令牌,站点将以
    未经授权的
    进行回复

    解决方案


    事实证明,服务池凭据没有更改TLS(?)的权限,当我将本地管理员帐户放入池中时,一切正常。

    我遇到了同样的问题,并最终设法解决了它。在我的例子中,客户端向其发送请求的端口没有SSL证书绑定。因此,我通过将SSL证书绑定到服务器端的端口解决了这个问题。一旦这样做了,这个例外就消失了

    对于从流中读取数据时出现此异常的任何人,这可能会有所帮助。在这样的循环中读取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。较大的缓冲区加快了进程,错误立即停止,很可能是因为总体下载速度提高了。但为什么下载速度对防止这种错误很重要呢

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