我正在使用一个商业应用程序,它抛出了一个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意味着一个零字节的数据包正在试图发送。

你怎么看?我猜这可能是不确定的,但也许有人见过这种东西?


当前回答

我们正在使用SpringBoot服务。我们的restTemplate代码如下所示:

@Bean
    public RestTemplate restTemplate(final RestTemplateBuilder builder) {

        return builder.requestFactory(() -> {
            final ConnectionPool okHttpConnectionPool =
                    new ConnectionPool(50, 30, TimeUnit.SECONDS);
            final OkHttpClient okHttpClient =
                    new OkHttpClient.Builder().connectionPool(okHttpConnectionPool)
                            // .connectTimeout(30, TimeUnit.SECONDS)
                            .retryOnConnectionFailure(false).build();

            return new OkHttp3ClientHttpRequestFactory(okHttpClient);
        }).build();
    }

在restTemplate设置ReadTimeout后,我们所有的调用都失败了。我们延长了时间,问题就解决了。

其他回答

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

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

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

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

发生此错误的另一种可能性是,如果您多次尝试使用无效凭据连接到第三方服务器,而像Fail2ban这样的系统正在阻止您的IP地址。

这不是代码中的错误。它来自。net的Socket实现。如果你使用EndReceive的重载实现,你将不会得到这个异常。

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

如果运行在。net 4.5.2服务中

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

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

解决方案

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