【Java】ClientAbortException

這個異常怎麼來的?

大致看了下tomcat源碼,是web容器裏拋出的一個異常。

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.connector;

import java.io.IOException;

/**
 * Wrap an IOException identifying it as being caused by an abort
 * of a request by a remote client.
 *
 * @author Glenn L. Nielsen
 */
public final class ClientAbortException extends IOException {

    private static final long serialVersionUID = 1L;


    //------------------------------------------------------------ Constructors

    /**
     * Construct a new ClientAbortException with no other information.
     */
    public ClientAbortException() {
        super();
    }


    /**
     * Construct a new ClientAbortException for the specified message.
     *
     * @param message Message describing this exception
     */
    public ClientAbortException(String message) {
        super(message);
    }


    /**
     * Construct a new ClientAbortException for the specified throwable.
     *
     * @param throwable Throwable that caused this exception
     */
    public ClientAbortException(Throwable throwable) {
        super(throwable);
    }


    /**
     * Construct a new ClientAbortException for the specified message
     * and throwable.
     *
     * @param message Message describing this exception
     * @param throwable Throwable that caused this exception
     */
    public ClientAbortException(String message, Throwable throwable) {
        super(message, throwable);
    }
}

這個是tomcat源碼中的一段,定義了這個異常。最開始的註釋裏寫到,當遠程客戶端關閉時,tomcat服務端會拋出這個異常。

在java裏,使用socket編程,底層是tcp協議,通信的雙方需要tcp三次握手,建立連接後才能通信。如果服務端在讀取客戶端輸入或者向客戶端輸出字節時,遠程客戶端主動斷開了連接,那麼根據socket接口,服務端會拋出一個IOException。tomcat裏針對這種場景下拋出的IOException,做了一層專門的異常封裝,就是上面的ClientAbortException。

看下拋出異常的部分:

    @Override
    public int realReadBytes() throws IOException {
        if (closed) {
            return -1;
        }
        if (coyoteRequest == null) {
            return -1;
        }

        if (state == INITIAL_STATE) {
            state = BYTE_STATE;
        }

        try {
            return coyoteRequest.doRead(this);
        } catch (IOException ioe) {
            // An IOException on a read is almost always due to
            // the remote client aborting the request.
            throw new ClientAbortException(ioe);
        }
    }

讀取字節。

    public void realWriteBytes(ByteBuffer buf) throws IOException {

        if (closed) {
            return;
        }
        if (coyoteResponse == null) {
            return;
        }

        // If we really have something to write
        if (buf.remaining() > 0) {
            // real write to the adapter
            try {
                coyoteResponse.doWrite(buf);
            } catch (CloseNowException e) {
                // Catch this sub-class as it requires specific handling.
                // Examples where this exception is thrown:
                // - HTTP/2 stream timeout
                // Prevent further output for this response
                closed = true;
                throw e;
            } catch (IOException e) {
                // An IOException on a write is almost always due to
                // the remote client aborting the request. Wrap this
                // so that it can be handled better by the error dispatcher.
                throw new ClientAbortException(e);
            }
        }

    }

寫入字節。

另外,拋出這個異常時,一般是高併發場景,需要客戶端主動斷開的時機恰好是服務端讀取或者寫入時,如果已經io完了,再斷開不會拋出這個異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章