Поделиться через


Set HttpWebRequest.KeepAlive = false to workaround issue casued by HttpWebRequest using a closed socket in very specific scenarios

Issue: System.Net.HttpWebRequest uses a socket that is closed in some special scenarios. (In this case it is due to some custom applications implement SSL not fully following RFC and so SSL alert caused socket to be closed forceily)

In this case, to workaround the issue, we can set System.Net.HttpWebRequest.KeepAlive = false

Symptom:

System.AccessViolationException could be thrown at System.Net.HttpWebRequest and Server side never get the request.

If checking the System.Net.HttpWebRequest object in memory dump, it could show somethign like below: (just for example)

ObjAddr 0b92baec:

Type:    System.Net.HttpWebRequest

---> System.Net.Connection:      0xb927fc8

---> System.Net.Sockets.NetworkStream:             0xb9292a8

---> System.Net.Sockets.Socket: 0xb9291b8

---> System.Net.Sockets.Socket Managed Handle Address:          0xb929218

---> System.Net.Sockets.Socket Unmanaged Sock Handle:            0xc10

Searching WinSock Context Table...

found

---> ws2_32!_CONTEXT_TABLE Address:              1a92e0

---> ws2_32!_CTX_LOOKUP_TABLE:         1a93a4

---> ws2_32!_CTX_HASH_TABLE:             209628

---> numBuckets:            1f

Mssock: Hash table entry for handle 00000c10 is NULL! Socket had been cleaned up. Exit.

If the above symptom is observed in debugging, we can workaround this by setting System.Net.HttpWebRequest.KeepAlive = false.

 

If it is web service reference, one way to set System.Net.HttpWebRequest.KeepAlive = false is to add the code below to Reference.cs in the cleint project.

 

protected override System.Net.WebRequest GetWebRequest(Uri uri)

{

    System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)base.GetWebRequest(uri);

    webRequest.KeepAlive = false;

    return webRequest;

}

 

If there is concern that this probably requires to modify the same every time the web Service is updated, we can add a class in client application code and inherit the Service class (which is in the reference.cs), for example:

    class MyModifiedService1 : Service1.Service1
    {
        protected override System.Net.WebRequest GetWebRequest(Uri uri)
        {

            System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)base.GetWebRequest(uri);

            webRequest.KeepAlive = false;

            return webRequest;

        }
    }

and, later use:
            MyModifiedService1 myService = new MyModifiedService1();

instead of:
            //Service1.Service1 myService = new Service1.Service1();

In this way, the code is in the client project and no need to do the modification again when service is updated.

Comments

  • Anonymous
    September 08, 2017
    We did tried implementing the keep alive settings to false and it gradually helped the windows service that calls an external API. Great job on this one.