Отмена в запросах WebApi

Существует несколько ресурсов об отмене запросов WebApi с помощью CancellationTokens, например (концепция, кажется, применима для всех последних версий):

Теперь я также узнал, что обычно для HTTP-соединения вы не открываете и не закрываете TCP-соединение каждый раз, когда отправляете новый запрос, но часто оставляете TCP-соединение открытым, по крайней мере, так я понял эту статью из MDN: типичный HTTP сессия

Итак, мой вопрос:

Если я выполняю HTTP-запросы от C#, будет ли базовое TCP-соединение создаваться и закрываться каждый раз, так что механизм, по сути, TCP-соединение закрыто и сервер может запросить отмену в токене?

Так значит ли это в конечном итоге, что я всегда открываю новое TCP-соединение для каждого запроса? Или есть что-то еще позади (также), которое также будет работать в сценарии, где TCP-соединение не будет закрыто?

2 ответа

Решение

Вот исходный код метода HttpWebrequest.Abort() из 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", "");
    }

Это ясно показывает, что TCP-соединения закрываются. Сервер по-своему реагирует на закрытый порт TCP. ссылка: https://serverfault.com/questions/147886/what-happens-when-a-http-request-is-terminated-prematurely

Вам не нужно беспокоиться о том, закрыто ли соединение или нет после обмена запросом-ответом HTTP, потому что это не влияет на механизм отмены. На это определенно влияет тот факт, что соединение закрывается во время обмена запросом-ответом HTTP, поскольку это вызывает отмену обработки запроса на стороне сервера в случае, если он обрабатывает токены отмены. Другими словами, если соединение закрыто до отправки ответа, независимо от того, какой тип соединения (сохраняется или для обмена), это является причиной для сервера инициировать процесс отмены.

Другие вопросы по тегам