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


103

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

在此处输入图片说明

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

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

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

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

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

Answers:


63

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

英文:与 (远程主机/服务器/ PC,在该服务运行)制成,但因为服务不可用那台机器,机器不知道如何处理的要求做的。

如果与计算机的连接不可用,则会看到另一个错误。我忘了它是什么,但这是“服务无法访问”或“不可用”的意思。

编辑-已添加

这很可能是由于防火墙阻止了端口而引起的,但是考虑到您说它是间歇性的(“有时客户端尝试连接”),这种可能性很小。我之所以不包括在内,是因为在回复之前我已经在心理上排除了它。


1
问题是,当我启动服务器时,有大约50个客户端连接到我的服务器。我已经在接受客户端时实现了一种等待信号..诸如while(Program.waitToFinishLoginAtClient == true && ajutor <30){Thread.Sleep(300); ajutor ++; } client = this.tcpListener.AcceptTcpClient(); Program.waitToFinishLoginAtClient = true; ...........和Program.waitToFinishAtClient在包含客户端的线程中被修改
Alex

这可能是“等待”的问题吗?
亚历克斯(Alex)

1
我应该随它去吗?不等吗?
亚历克斯(Alex),15:

1
我认为等待是问题所在。我不太了解您的代码,可以肯定,但这听起来很可能。只是好奇您是否以“艰苦的方式”构建了自己的服务,或者是否正在使用WCF甚至是Remoting来实现这一点……
David

基于此处的少量代码,在我看来,如果每个连接都在单独的线程中,则可以避免“等待”问题。就在情况下的猜测是正确的,这里是一个多线程的TCP服务与多线程,可以帮助您的例子:switchonthecode.com/tutorials/...
大卫·

180

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

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

编辑

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

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

TLS握手 -此协议用于交换双方通过TLS交换实际应用程序数据所需的所有信息。

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

ServerHello-服务器以ServerHello消息作为响应,其中包含所选的协议版本...所选的协议版本应该是客户端和服务器支持的最高版本。例如,如果客户端支持TLS版本1.1,而服务器支持版本1.2,则应选择版本1.1;否则,请选择1.1。不应选择1.2版本。


8
这救了我!谢啦。在我的调试器中,我正在尝试在测试时调用https服务,并且遇到了OP所遇到的问题。
布莱尔·霍尔姆斯

6
我们是否了解这如何/为什么工作?我一直在努力进行PostAsync调用,这似乎也可以解决我的错误。很高兴它有效,但我也想知道为什么。
凯文·马特洛克

1
@HansVonn谢谢!节省了我很多时间-关于它为什么起作用这只是限制了您在连接时使用的TLS版本。
2017年

1
简直不敢相信这让我再一次!谢谢
塞尔吉奥·

2
谢谢!这让我发疯。
mknopf

34

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

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

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


7
哦,天哪,非常感谢!我已经坚持了很长时间,并且检查了Web应用程序的SSL设置,并将最小值设置为1.2而不是1.0。当我将其更改回1.0并重新启动Web应用程序后,它开始工作了!非常感谢!
梅森

1
非常感谢@hugo-hilário,它对我也很有效!您到底是如何找到这样一个棘手的解决方案的!:D
hosjay

@hosjay对我来说也是个地狱:)
雨果·

3
救了我的同伴!
Nitesh

我的Azure Function v2遇到了这个问题
Pieter Heemeryck

17

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

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

帮助我的诀窍是退出使用WebRequest并改为使用HttpWebRequest。HttpWebRequest允许我进行以下三个重要设置:

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

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

1
这个答案为我解决了同样的问题。我在IIS7的Http响应标头部分中关闭了“保持活动”状态
drzounds 2016年

我应该补充一点,我还必须将此代码添加到具有该行为的Web服务的Reference.cs中。受保护的重写System.Net.WebRequest GetWebRequest(Uri uri){System.Net.HttpWebRequest webRequest =(System.Net.HttpWebRequest)base.GetWebRequest(uri); webRequest.KeepAlive = false; 返回webRequest; }
drzounds '16

11

从我们的一台服务器对HTTPS服务的调用还引发了“ 无法从传输连接读取数据:现有连接被强制关闭 ”异常。HTTP服务运行正常。使用Wireshark看到这是TLS握手失败。最终是服务器上的密码套件需要更新。


这就是我正在发生的事情。已将过期证书发送到SSL连接。续签证书并工作。
Guilherme de Jesus Santos

8

据《汉斯·沃恩》回复。

在进行呼叫之前添加以下行可解决此问题:

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

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


1
非常感谢你。你让我今天一整天都感觉很好。如果我提到在此之前,我还测试了禁用防火墙并添加ServicePointManager.ServerCertificateValidationCallback的效果,但对某些用户而言可能无效,这可能对某些人有用。
特勤

5

这对于间歇性问题无济于事,但对其他有类似问题的人可能有用。

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


2

由于某些原因,与服务器的连接已丢失。可能是服务器显式关闭了连接,或者服务器上的错误导致其意外关闭。或客户端和服务器(交换机或路由器)之间的某个东西断开了连接。

可能是服务器代码引起了问题,而事实并非如此。如果您有权访问服务器代码,则可以在其中进行一些调试,以告诉您何时关闭客户端连接。这可能会给您一些指示何时以及为什么断开连接的信息。

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


2

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

System.Net.ServicePointManager.Expect100Continue = false;

似乎服务器方式中存在一个不支持100连续行为的代理。


1

我过去遇到过这个问题。我正在使用 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!

        }

我认为该程序必须先读取连接,然后再执行任何操作,我不知道,如果我做错了,请更正我。但是根据我的研究,这不是代码问题-实际上是机器本身造成的。

编码愉快!


1
System.Net.ServicePointManager.Expect100Continue = false;

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


0

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


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

在这里另一个问题的回答有一个我们用来添加条目的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服务器证书丢失了,并且没有安装在几个服务器上。


0

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



0

对我来说,这是一个问题,在IIS绑定中它具有Web服务器的IP地址。我将其更改为使用所有未分配的IP,并且我的应用程序开始工作。


0

我遇到了使用adomd向Microsoft Analytic Services运行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

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" />

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

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.