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

问题描述 投票:71回答:15

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

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

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

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

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

可能是什么导致了这个问题?请注意,它不会一直发生

c# .net ioexception
15个回答
48
投票

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

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

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

编辑 - 添加

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


1
投票
System.Net.ServicePointManager.Expect100Continue = false;

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


0
投票

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


0
投票

我们有一个非常类似的问题,客户的网站试图连接到我们的Web API服务并获得相同的消息。当IIS运行的服务器上没有代码更改或Windows更新时,这种情况就开始发生了。

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

[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,但上面的注册表项可以帮助诊断问题。


0
投票

这种情况发生在我身上的原因是我在我的DI提供商中有一个递归依赖。在我的情况下,我有:

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

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

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

0
投票

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


0
投票

有一个类似的问题,并根据我使用的应用程序和我们是否绕过防火墙/负载均衡器得到以下错误:

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

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

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


133
投票

我在调用Web服务时收到此错误。该问题还与运输级安全有关。我可以通过网站项目调用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。


26
投票

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

我不知道从现在开始这是否是默认值,但将其更改回1.0会使其正常工作。

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


15
投票

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

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步:将协议版本设置为版本10
  • 第3步:限制服务点数

10
投票

从我们的一台服务器调用HTTPS服务也抛出“无法从传输连接读取数据:现有连接被强行关闭”异常。但是,HTTP服务运行良好。使用Wireshark看到它是TLS握手失败。结束了服务器上的密码套件需要更新。


4
投票

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

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


2
投票

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

它可能是引起问题的服务器代码,也可能不是。如果您可以访问服务器代码,则可以在其中进行一些调试以告知您何时关闭客户端连接。这可能会告诉您连接被删除的时间和原因。

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


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!

        }

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

快乐的编码!


2
投票

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

System.Net.ServicePointManager.Expect100Continue = false;

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

© www.soinside.com 2019 - 2024. All rights reserved.