Thomas
Thomas

Reputation: 473

..The underlying connection was closed: An unexpected error occurred on a receive

I have the following code:

private Uri currentUri;

private void Form1_Load(object sender, EventArgs e)
{
    currentUri = new Uri(@"http://www.stackoverflow.com");
    HttpWebRequest myRequest = (HttpWebRequest) HttpWebRequest.Create("http://www.stackoverflow.com");
    WebProxy myProxy = new WebProxy("120.198.230.8:81");
    myRequest.Proxy = myProxy;

    HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();

    webBrowser1.DocumentStream = myResponse.GetResponseStream();

    webBrowser1.Navigating += new WebBrowserNavigatingEventHandler(webBrowser1_Navigating);
}

void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    if (e.Url.AbsolutePath != "blank")
    {
        currentUri = new Uri(currentUri, e.Url.AbsolutePath);
        HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(currentUri);

        HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();

        webBrowser1.DocumentStream = myResponse.GetResponseStream();
        e.Cancel = true;
    }
}

after compiling:

error: An unhandled exception of type 'System.Net.WebException' occurred in System.dll

Additional information: The underlying connection was closed: An unexpected error occurred on a receive.

at line HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();

Please help me.

Upvotes: 47

Views: 496545

Answers (9)

Anton Shepelev
Anton Shepelev

Reputation: 1011

To expand on Bartho Bernsmann's answer, I should like to add that one can have a universal, future-proof implementation at the expense of a little reflection:

static void AllowAllSecurityPrototols()
{   int                  i, n;
    Array                types;
    SecurityProtocolType combined;

    types = Enum.GetValues( typeof( SecurityProtocolType ) ); 
    combined = ( SecurityProtocolType )types.GetValue( 0 );

    n = types.Length;
    for( i = 1; i < n; i += 1 )
    {   combined |= ( SecurityProtocolType )types.GetValue( i );  }

    ServicePointManager.SecurityProtocol = combined;
}

I invoke it in the static constructor of the class that accesses the internet. As new protocols are added to the enumeration, no changes to this method will be required to allow them.

Update—a safer version

As John - Not A Number objserved in the comments, the method above is colossally dangerous, as it enables all the available protocols, including those very old, obsolete, and insufficiently secure. To take this into account, I have created a safer method, which enables only a specified number of the latest protocols:

static void AllowLatestSecurityPrototols( int last_n )
{   int                  i, n, i_max;
    Array                types;
    SecurityProtocolType combined;

    types = Enum.GetValues( typeof( SecurityProtocolType ) ); 
    n = types.Length;
    combined = ( SecurityProtocolType )types.GetValue( 0 );

    if( last_n > n ) i_max = n;
    else             i_max = last_n;
    for( i = 1; i <= i_max; i += 1 )
    {   combined |= ( SecurityProtocolType )types.GetValue( n - i );
        Console.WriteLine(( SecurityProtocolType )types.GetValue( n - i ));
    }

    ServicePointManager.SecurityProtocol = combined;
}

For example, AllowLatestSecurityPrototols(2) will allow only the two latest protocols, which in my environment are TLS1.3 and TLS1.2. Granted, this is still quite insequre, but much less so than the original.

Similartly, one may write a function that enables protocols later than the certain given one, but its invocation will have to be updated from time to time:

static void AllowSecurityProtsFrom( SecurityProtocolType earliest )
{   int                  i, n;
    Array                types;
    SecurityProtocolType combined;
    SecurityProtocolType prot;

    types = Enum.GetValues( typeof( SecurityProtocolType ) ); 
    n = types.Length;
    combined = ( SecurityProtocolType )types.GetValue( 0 );

    for( i = 0; i < n; i += 1 )
    {  prot = ( SecurityProtocolType )types.GetValue( i );
        if( prot < earliest ) continue;
    }

    ServicePointManager.SecurityProtocol = combined;
}

Upvotes: 0

Chuenkei Sit
Chuenkei Sit

Reputation: 51

I met the same exception "Exception calling "ExecuteQuery" with "0" argument(s): "The underlying connection was closed: An unexpected error occurred on a receive."" with powershell script block`

 #Setup Credentials to connect
        $Username="[email protected]"  
        $Password="pwd4user"
        $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
        #$Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username, $securePassword)
     
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred
 
        #Get the Library and Its Root Folder
        $Library=$Ctx.web.Lists.GetByTitle($LibraryName)
        $Ctx.Load($Library)
        $Ctx.Load($Library.RootFolder)
        $Ctx.ExecuteQuery()` 

above code block can works on one of my pc, but on another PC it is not, after i added this line [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 at the header, but run it again I got another exception "Exception calling "ExecuteQuery" with "0" argument(s): "The partner returned a bad sign-in name or password error. For more information, see Federation Error -handling Scenarios."" i can confirm there is nothing wrong with my credentials, because it can works on one pc. then i search the exception info, i get this url: The partner returned a bad sign-in name or password error. For more information, see Federation Error-handling Scenarios.

the site figure out that the proxy may cause this exception, then i notice the proxy were different on this two PCs, so i changed the proxy on the pc which the script not works. finally the all exception were gone.

Upvotes: 1

Amol Shiledar
Amol Shiledar

Reputation: 393

My Hosting server block requesting URL And code site getting the same error Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

enter image description here

After a lot of time spent and apply the following step to resolve this issue

  1. Added line before the call web URL

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

  2. still issue not resolve then I upgrade .net version to 4.7.2 but I think it's optional

  3. Last change I have checked my hosting server security level which causes to TLS handshaking for this used "https://www.ssllabs.com/ssltest/index.html" site
    and also check to request URL security level then I find the difference is requested URL have to enable a weak level Cipher Suites you can see in the below image

enter image description here

Now here are my hosting server supporting Cipher Suites

enter image description here

here is called if you have control over requesting URL host server then you can sync this both server Cipher Suites. but in my case, it's not possible so I have applied the following script in Windows PowerShell on my hosting server for enabling required weak level Cipher Suites.

Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
Enable-TlsCipherSuite -Name "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
Enable-TlsCipherSuite -Name "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
Enable-TlsCipherSuite -Name "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_256_GCM_SHA384"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_128_GCM_SHA256"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_256_CBC_SHA256"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_128_CBC_SHA256"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_256_CBC_SHA"
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_AES_256_CBC_SHA"

after applying the above script my hosting server Cipher Suites level look like

enter image description here

Then my issue resolved.

Note: server security level downgrade is not a recommended option.

Upvotes: 2

Bartho Bernsmann
Bartho Bernsmann

Reputation: 2483

Setting the HttpWebRequest.KeepAlive to false didn't work for me.

Since I was accessing a HTTPS page I had to set the Service Point Security Protocol to Tls12.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Notice that there are other SecurityProtocolTypes: SecurityProtocolType.Ssl3, SecurityProtocolType.Tls, SecurityProtocolType.Tls11

So if the Tls12 doesn't work for you, try the three remaining options.

Also notice that you can set multiple protocols. This is preferable on most cases.

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

Edit: Since this is a choice of security standards it's obviously best to go with the latest (TLS 1.2 as of writing this), and not just doing what works. In fact, SSL3 has been officially prohibited from use since 2015 and TLS 1.0 and TLS 1.1 will likely be prohibited soon as well. source: @aske-b

Upvotes: 84

Anjan Kant
Anjan Kant

Reputation: 4316

I was working also on web scraping project and same issue found, below code applied and it worked nicely. If you are not aware about TLS versions then you can apply all below otherwise you can apply specific.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;

Upvotes: 0

Rahul Patil
Rahul Patil

Reputation: 169

Before Execute query I put the statement as below and it resolved my error. Just FYI in case it will help someone.

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; ctx.ExecuteQuery();

Upvotes: 1

Daniyal Saleem
Daniyal Saleem

Reputation: 83

  • .NET 4.6 and above. You don’t need to do any additional work to support TLS 1.2, it’s supported by default.
  • .NET 4.5. TLS 1.2 is supported, but it’s not a default protocol. You need to opt-in to use it. The following code will make TLS 1.2 default, make sure to execute it before making a connection to secured resource:
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  • .NET 4.0. TLS 1.2 is not supported, but if you have .NET 4.5 (or above) installed on the system then you still can opt in for TLS 1.2 even if your application framework doesn’t support it. The only problem is that SecurityProtocolType in .NET 4.0 doesn’t have an entry for TLS1.2, so we’d have to use a numerical representation of this enum value:
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  • .NET 3.5 or below. TLS 1.2 is not supported. Upgrade your application to more recent version of the framework.

Upvotes: 7

Hugh Jeffner
Hugh Jeffner

Reputation: 2946

None of the solutions out there worked for me. What I eventually discovered was the following combination:

  • Client system: Windows XP Pro SP3
  • Client system has .NET Framework 2 SP1, 3, 3.5 installed
  • Software targeting .NET 2 using classic web services (.asmx)
  • Server: IIS6
  • Web site "Secure Communications" set to:
    • Require Secure Channel
    • Accept client certificates

enter image description here

Apparently, it was this last option that was causing the issue. I discovered this by trying to open the web service URL directly in Internet Explorer. It just hung indefinitely trying to load the page. Disabling "Accept client certificates" allowed the page to load normally. I am not sure if it was a problem with this specific system (maybe a glitched client certificate?) Since I wasn't using client certificates this option worked for me.

Upvotes: 1

Nagaraj S
Nagaraj S

Reputation: 13474

The underlying connection was closed: An unexpected error occurred on a receive.

This problem occurs when the server or another network device unexpectedly closes an existing Transmission Control Protocol (TCP) connection. This problem may occur when a time-out value on the server or on the network device is set too low. To resolve this problem, see resolutions A, D, E, F, and O. The problem can also occur if the server resets the connection unexpectedly, such as if an unhandled exception crashes the server process. Analyze the server logs to see if this may be the issue.

Resolution

To resolve this problem, make sure that you are using the most recent version of the .NET Framework.

Add a method to the class to override the GetWebRequest method. This change lets you access the HttpWebRequest object. If you are using Microsoft Visual C#, the new method must be similar to the following.

class MyTestService:TestService.TestService
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
        HttpWebRequest webRequest = (HttpWebRequest) base.GetWebRequest(uri);
        //Setting KeepAlive to false
        webRequest.KeepAlive = false;
        return webRequest;
    }
}

Excerpt from KB915599: You receive one or more error messages when you try to make an HTTP request in an application that is built on the .NET Framework 1.1 Service Pack 1.

Upvotes: 27

Related Questions