Sjoerd222888
Sjoerd222888

Reputation: 3486

Cancellation in WebApi requests

There are several resources about cancellation of WebApi requests with CancellationTokens, e.g. (the concept seems to apply for all recent versions):

Now I also learned that typically for a HTTP connection you do not open and close the TCP connection every time you send a new request but often you leave the TCP connection open, at least that is how I understood this article from MDN: A typical HTTP session.

So my question is:

If I am doing HTTP requests from C#, will the underlying TCP connection be build up and closed every time, so that the mechanism is basically a TCP connection is closed and the server can request the cancellation in the token?

So does this in the end relay on the fact that I always open a new TCP connection for each request? Or is there something else behind (as well) that would also work in a scenario where the TCP connection would not get closed?

Upvotes: 1

Views: 1247

Answers (2)

Dmytro Mukalov
Dmytro Mukalov

Reputation: 1994

You don't need to bother whether a connection is closed or not after an HTTP request-response exchange because it has no influence on the cancellation mechanism. What definitely has an influence is the fact that connection is closed during the an HTTP request-response exchange as this triggers the cancellation of the request processing on the server side in case if it handles the cancellation tokens. So in other words if connection is closed before the response is sent regardless of what type the connection is (keep alive or per exchange) this is a reason for server to initiate the cancellation process.

Upvotes: 0

Manish Jha
Manish Jha

Reputation: 40

Here is the source code for HttpWebrequest.Abort() method from Github.

     private void Abort(Exception exception, int abortState)
    {
        GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::Abort()");
        if (Logging.On) Logging.Enter(Logging.Web, this, "Abort", (exception == null? "" :  exception.Message));

        if(Interlocked.CompareExchange(ref m_Aborted, abortState, 0) == 0) // public abort will never drain streams
        {
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::Abort() - " + exception);

            NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestAborted);

            m_OnceFailed = true;
            CancelTimer();

            WebException webException = exception as WebException;
            if (exception == null)
            {
                webException = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled);
            }
            else if (webException == null)
            {
                webException = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), exception, WebExceptionStatus.RequestCanceled, _HttpResponse);
            }

            try
            {

                    // Want to make sure that other threads see that we're aborted before they set an abort delegate, or that we see
                    // the delegate if they might have missed that we're aborted.
                    Thread.MemoryBarrier();
                    HttpAbortDelegate abortDelegate = _AbortDelegate;

                    if (abortDelegate == null || abortDelegate(this, webException))
                    {
                        // We don't have a connection associated with this request

                        SetResponse(webException);
                    }
                    else
                    {
                        // In case we don't call SetResponse(), make sure to complete the lazy async result
                        // objects. abortDelegate() may not end up in a code path that would complete these
                        // objects.
                        LazyAsyncResult writeAResult = null;
                        LazyAsyncResult readAResult = null;

                        if (!Async)
                        {
                            lock (this)
                            {
                                writeAResult = _WriteAResult;
                                readAResult = _ReadAResult;
                            }
                        }

                        if (writeAResult != null)
                            writeAResult.InvokeCallback(webException);

                        if (readAResult != null)
                            readAResult.InvokeCallback(webException);
                    }

                    if (!Async)
                    {
                        LazyAsyncResult chkConnectionAsyncResult = ConnectionAsyncResult;
                        LazyAsyncResult chkReaderAsyncResult = ConnectionReaderAsyncResult;

                        if (chkConnectionAsyncResult != null)
                            chkConnectionAsyncResult.InvokeCallback(webException);
                        if (chkReaderAsyncResult != null)
                            chkReaderAsyncResult.InvokeCallback(webException);
                    }

                    if (this.IsWebSocketRequest && this.ServicePoint != null)
                    {
                        this.ServicePoint.CloseConnectionGroup(this.ConnectionGroupName);
                    }

            }
            catch (InternalException)
            {
            }
        }

        if(Logging.On)Logging.Exit(Logging.Web, this, "Abort", "");
    }

This clearly shows that TCP connections are being closed. The server responds in its own way to a closed TCP port. link : https://serverfault.com/questions/147886/what-happens-when-a-http-request-is-terminated-prematurely

Upvotes: 1

Related Questions