h-rai
h-rai

Reputation: 3964

System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send

I'm posting some data to the server but the application is throwing exception. Here's the code.

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

        Dim bytes As Byte() = Encoding.UTF8.GetBytes(xml)
        Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        request.Method = "POST"
        request.ContentLength = bytes.Length
        request.ContentType = "text/xml"
        Using requestStream As Stream = request.GetRequestStream()
            requestStream.Write(bytes, 0, bytes.Length)
        End Using

Here's the exception stacktrace.

System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.TlsStream.CallProcessAuthentication(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()

I've updated my code as per the answer/s here but to no avail. I've also checked that the proxy server has been disconnected.

Upvotes: 2

Views: 3605

Answers (2)

Stefan Steiger
Stefan Steiger

Reputation: 82136

The highest enabled TLS version of the .NET framework you are using on the client-side is incompatible with the current TLS version used by the server.

TLS Compatiblity

This is causing an empty response.

System.Net.WebException: The underlying connection was closed:
An unexpected error occurred on a send. ---> System.IO.IOException:
Received an unexpected EOF or 0 bytes from the transport stream. at
System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)

You either need to update your .NET framework, or enable TLS-compatibility in the registry,

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

or enable it in your .NET code using System.Net.ServicePointManager.SecurityProtocol.

e.g.

namespace Gdp
{


    public static class TlsFix
    {


        public static void UseLatestAvailableSslProtocol()
        {
            try
            {
                // Using TLS 1.3 
                System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)12288 | (System.Net.SecurityProtocolType)3072 | (System.Net.SecurityProtocolType)768 | System.Net.SecurityProtocolType.Tls;
                System.Console.WriteLine("Using TLS 1.3");
            }
            catch (System.NotSupportedException) // exNoTls13'
            {
                try
                {
                    // Using TLS 1.2 
                    System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072 | (System.Net.SecurityProtocolType)768 | System.Net.SecurityProtocolType.Tls;
                    System.Console.WriteLine("Using TLS 1.2");
                }
                catch (System.NotSupportedException) // exNoTls12 
                {
                    try
                    {
                        // Using TLS 1.1 
                        System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)768 | System.Net.SecurityProtocolType.Tls;
                        System.Console.WriteLine("Using TLS 1.1");
                    }
                    catch (System.NotSupportedException) // exNoTls11
                    {
                        // Using TLS 1.0 
                        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;
                    } // End Catch TLS 1.1 

                } // End Catch TLS 1.2 

            } // End Catch TLS 1.3 

        } // End Sub UseLatestAvailableSslProtocol 


    } // End Class TlsFix 


} // End Namespace 

If you are using an old version of .NET-Core, you can set this in the HttpClientHandler that you pass to your HttpClient

internal class HttpClientHelper 
{


    public static System.Net.Http.HttpClient Factory()
    {
        // For .NET 5.0+
        System.Net.Http.HttpClientHandler handler = new System.Net.Http.HttpClientHandler
        {
            SslProtocols = System.Security.Authentication.SslProtocols.Tls12 |
                           System.Security.Authentication.SslProtocols.Tls13
        };

        System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(handler);
        return client;
    } // End Function Factory 


} // End Class HttpClientHelper 

TLS 1.1 is deprecated.
There are also plans to deprecate obsolete key-exchange methods in TLS 1.2.
So you better upgrade to TLS 1.3 STAT/ASAP.


(and by the way, Google Chrome has already dropped support for TLS 1.1 in Version 72+, and planned removal in Chrome 81 anno 2020)

Upvotes: 0

h-rai
h-rai

Reputation: 3964

I was able to find that the server that I was POSTing to was only accepting requests having security protocol TLS 1.1 and above. The application is running on .NET 3.5 which only supports SSL and TLS 1.0 protocols. The solution will be to upgrade the application to .NET 4.5 and use TLS 1.1 and above to make requests to the HTTP service.

Upvotes: 1

Related Questions