无法从传输连接读取数据:远程主机强制关闭现有连接

时间:2011-03-24 14:25:00

标签: c# .net ioexception

我有一个服务器应用程序,有时,当客户端尝试连接时,我收到以下错误:

enter image description here

注意:“无法从客户端获取流或登录失败”是我在catch语句中添加的文本

和它停止的行(sThread:第96行)是:

tcpClient = (TcpClient)client;
clientStream = tcpClient.GetStream();
sr = new StreamReader(clientStream);
sw = new StreamWriter(clientStream);

// line 96:                 
a = sr.ReadLine();

可能导致此问题的原因是什么?请注意,它不会一直发生

22 个答案:

答案 0 :(得分:125)

调用网络服务时收到此错误。该问题还与运输级安全有关。我可以通过网站项目调用Web服务,但是当在测试项目中重用相同的代码时,我会得到一个包含此消息的WebException。在进行调用之前添加以下行解决了问题:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

修改

  

System.Net.ServicePointManager.SecurityProtocol - 此属性   选择安全套接字层(SSL)或传输的版本   层安全性(TLS)协议,用于使用的新连接   仅限安全超文本传输​​协议(HTTPS)方案;现有   连接没有改变。

我认为在选择协议版本时,在TLS握手期间SecurityProtocol配置很重要。

  

TLS handshake - 该协议用于交换双方为通过TLS交换实际应用数据所需的所有信息。

     

ClientHello - 客户端发送ClientHello消息,指定它支持的最高TLS协议版本...

     

ServerHello - 服务器使用包含所选协议版本的ServerHello消息进行响应...所选协议版本应该是客户端和服务器都支持的最高版本。例如,如果客户端支持TLS 1.1版并且服务器支持1.2版,则应选择版本1.1;不应选择版本1.2。

答案 1 :(得分:45)

此错误通常表示目标计算机正在运行,但您尝试连接的服务不可用。 (它停止,崩溃或忙于另一个请求。)

英文: 已建立与计算机(服务运行的远程主机/服务器/ PC)的连接,但由于 该服务器上的服务不可用,因此该计算机没有知道如何处理请求。

如果与机器的连接不可用,您会看到不同的错误。我忘记了它是什么,但它是“服务无法访问”或“不可用”。

修改 - 添加

这可能是由防火墙阻塞端口引起的,但鉴于你说它是间歇性的(“有时在客户端尝试连接时”),这是不太可能的。我最初没有把它包括在内,因为我在回答之前已经在精神上排除了它。

答案 2 :(得分:22)

我的具体情况是Azure应用服务的最低TLS版本更改为1.2

我现在不知道这是否是默认设置,但是将其更改回1.0即可正常工作。

您可以访问“ SSL设置”中的设置。

答案 3 :(得分:14)

不确定这些博客文章中的哪些修补程序有帮助,但其中一个已为我排序此问题...

http://briancaos.wordpress.com/2012/07/06/unable-to-read-data-from-the-transport-connection-the-connection-was-closed/

帮助我的技巧是使用WebRequest退出并使用HttpWebRequest代替。 HttpWebRequest允许我使用3个重要设置:

http://briancaos.wordpress.com/2012/06/15/an-existing-connection-was-forcibly-closed-by-the-remote-host/

  • 第1步:禁用KeepAlive
  • 第2步:将ProtocolVersion设置为Version10
  • 第3步:限制服务点数

答案 4 :(得分:11)

根据“汉斯·沃恩”的回复。

在致电前添加以下行可解决此问题:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

在添加安全协议并正常工作之后,但是我必须在每个不正常的API调用之前添加。我只是将.net Framework版本至少升级到4.6,并且按预期工作不需要在每个API调用之前添加。

答案 5 :(得分:8)

从我们的某个服务器调用HTTPS服务也导致" 无法从传输连接中读取数据:现有连接被强行关闭"例外。但是,HTTP服务运行良好。使用Wireshark看到它是TLS握手失败。结束了服务器上的密码套件需要更新。

答案 6 :(得分:3)

这对间歇性问题不会有帮助,但对于遇到类似问题的其他人可能会有用。

我克隆了一个虚拟机,并在一个具有新IP地址的不同网络上启动了虚拟机,但未更改IIS中的绑定。 Fiddler告诉我"无法从传输连接读取数据:现有连接被远程主机强行关闭"和IE告诉我"在高级设置"中打开TLS 1.0,TLS 1.1和TLS 1.2。更改绑定到新的IP地址解决了它。

答案 7 :(得分:2)

由于某种原因,与服务器的连接丢失了。可能是服务器明确关闭了连接,或者服务器上的错误导致它意外关闭。或者客户端和服务器(交换机或路由器)之间的某些东西丢弃了连接。

可能是导致问题的服务器代码,而且可能不是。如果您可以访问服务器代码,则可以在其中进行一些调试以告知您何时关闭客户端连接。这可能会给你一些关于连接被删除的时间和原因的指示。

在客户端上,您必须编写代码以考虑服务器随时出现故障的可能性。这就是它的方式:网络连接本质上是不可靠的。

答案 8 :(得分:2)

我过去遇到了这个问题。我正在使用 PostgreSQL ,当我运行我的程序时,有时它会连接,有时它会抛出这样的错误。

当我试验我的代码时,我将我的连接代码放在公共表单下面的第一行。这是一个例子:

在:

    public Form1()
        {
        //HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
        //CODE
        //CODE AGAIN
        //ANOTHER CODE
        //CODE NA NAMAN
        //CODE PA RIN!





        //Connect to Database to generate auto number
        NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
        iConnect.Open();
        NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
        NpgsqlDataReader iRead = iQuery.ExecuteReader();
        NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);

        DataSet iDataSet = new DataSet();
        iAdapter.Fill(iDataSet, "ID");

        MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
        }

现在:

    public Form1()
        {
        //Connect to Database to generate auto number
        NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
        iConnect.Open();
        NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
        NpgsqlDataReader iRead = iQuery.ExecuteReader();
        NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);

        DataSet iDataSet = new DataSet();
        iAdapter.Fill(iDataSet, "ID");

        MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());





        //HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
        //CODE
        //CODE AGAIN
        //ANOTHER CODE
        //CODE NA NAMAN
        //CODE PA RIN!

        }

我认为该程序在做任何事之前必须首先阅读连接,我不知道,如果我错了,请纠正我。但根据我的研究,它不是代码问题 - 实际上它来自机器本身。

快乐的编码!

答案 9 :(得分:2)

这解决了我的问题。我在提出请求之前添加了这一行:

@RestControllerAdvice
public class SampleAdvice implements ResponseBodyAdvice<Sample>{

    @Override
    public Sample beforeBodyWrite(Sample sample, MethodParameter arg1, MediaType arg2,
            Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest arg4, ServerHttpResponse arg5) {
        // Get a handle to your response object and make changes here
        sample.setProperty("Overridden Property");
        return sample;
    }

    @Override
    public boolean supports(MethodParameter arg0, Class<? extends HttpMessageConverter<?>> arg1) {
        return true;
    }
}

服务器的方式似乎有一个不支持100-continue行为的代理。

答案 10 :(得分:1)

{{1}}

由于在Web服务器上实现代理服务器的原因,有时会发生此问题。通过在调用发送服务之前放置此行来绕过代理服务器。

答案 11 :(得分:0)

我们遇到了一个非常相似的问题,即客户的网站试图连接到我们的Web API服务并获得相同的消息。在没有代码更改或运行IIS的服务器上没有Windows更新的情况下,这完全是突然发生的。

在我们的案例中,事实证明调用网站使用的是仅支持TLS 1.0的.Net版本,并且由于某些原因,运行IIS的服务器已停止接受TLS 1.0调用。为了诊断我们必须通过IIS服务器上的注册表显式启用TLS,然后重新启动该服务器。这些是注册码:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

If that doesn't do it, you could also experiment with adding the entry for SSL 2.0:


    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
    "DisabledByDefault"=dword:00000000
    "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
    "DisabledByDefault"=dword:00000000
    "Enabled"=dword:00000001

我对another question here的回答有一个我们用来添加条目的powershell脚本:

注意:启用旧的安全协议不是一个好主意,在我们的案例中,正确的答案是让客户端网站更新其代码以使用TLS 1.2,但是上面的注册表项可以帮助您首先诊断问题。

答案 12 :(得分:0)

当代理服务器中的服务不可用时会出现此问题。我们可以绕过代理服务器。 在开始服务之前,应用此代码行。

System.Net.ServicePointManager.Expect100Continue = false;

Further details

答案 13 :(得分:0)

对于那些以后可能会发现此问题的人,在.NET 4.6版之后,我也遇到了这个问题。

确保检查web.config文件中的以下行:

<compilation debug="true" targetFramework="4.5">
...
<httpRuntime targetFramework="4.5" />

如果在服务器上运行4.6.x或更高版本的.NET,请确保调整这些targetFramework值以使其与服务器上框架的版本匹配。如果您的版本读取的版本低于4.6.x,那么我建议您升级.NET并使用较新的版本,除非您的代码依赖于较旧的版本(在这种情况下,应考虑对其进行更新)。

我将targetFrameworks更改为4.7.2,问题消失了:

<compilation debug="true" targetFramework="4.7.2">
...
<httpRuntime targetFramework="4.7.2" />

较新的框架通过使用最佳的可用协议并阻止不安全或过时的协议来解决此问题。如果您尝试连接或呼叫的远程服务出现此错误,则可能是它们不再支持旧协议。

答案 14 :(得分:0)

我遇到了使用adomd向Microsoft解析服务运行mdx查询的python clr错误

我在 Hans Vonn 的帮助下解决了此问题,以下是 python 版本:

clr.AddReference("System.Net")
from System.Net import ServicePointManager, SecurityProtocolType 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls

答案 15 :(得分:0)

另一种选择是检查使用try-catch块并首先捕获WebException生成的错误代码。

在我的情况下,由于HTTPS URL上的证书问题,错误代码为“ SendFailure”,一旦我点击HTTP,问题就解决了。

https://docs.microsoft.com/en-us/dotnet/api/system.net.webexceptionstatus?redirectedfrom=MSDN&view=netframework-4.8

答案 16 :(得分:0)

尝试首先检查是否可以建立握手。在上传文件之前,我曾遇到过这个问题,当我删除上传并检查是否可以在给定参数的情况下登录时,才发现该问题是不存在的路由。

答案 17 :(得分:0)

发生了类似的问题,并根据我使用的应用程序以及是否绕过防火墙/负载均衡器而出现以下错误:

  

与[blah](对于#136)的HTTPS握手失败。   System.IO.IOException无法从传输读取数据   连接:远程强行关闭了现有连接   主机

  

ReadResponse()失败:服务器未对此请求返回完整的响应。服务器返回了0个字节。

原来的问题是SSL服务器证书丢失了,并且没有安装在几个服务器上。

答案 18 :(得分:0)

如果域上具有https证书,请确保将IIS绑定到域名的https。 在IIS中->选择您的域->单击绑定 “站点绑定”窗口打开。为https添加绑定。

答案 19 :(得分:0)

发生这种情况的原因是我的DI提供程序具有递归依赖性。就我而言,我有:

services.AddScoped(provider => new CfDbContext(builder.Options));
services.AddScoped(provider => provider.GetService<CfDbContext>());

修复是仅删除第二个作用域服务注册

services.AddScoped(provider => new CfDbContext(builder.Options));

答案 20 :(得分:0)

我有第三方应用程序(Fiddler)正在运行以尝试查看正在发送的请求。关闭此应用程序为我修复了

答案 21 :(得分:-1)

我收到这个错误只是因为我试图建立到一个只支持 https 的服务器的 http 连接。将请求协议从 http 更改为 https 从而解决了它。