Golang Detecting HTTP Connection Disconnects

Source: Internet
Author: User

Consider HTTP-based RPC, or the mechanism by which the HTTP server proactively notifies the client, that is, HTTP long-polling, which means that the client initiates a long connection, and the server block does not respond until: timeout, for example, after 5 seconds, we respond to a keepalive to the client, It means that there is nothing yet, please continue to polling. To get the result, this could be any time, such as 300 milliseconds, 1100 milliseconds, 2300 milliseconds to get an event that responds to the client and implements an event asynchronous notification.

This allows RPC to be very efficient between the client and server, and is notified only when there is an event. However, there is actually a situation that needs to be handled: when the client disconnects, such as when the client sets a 3-second TCP request timeout, or because the OS reclaims the FD when the client crash, the server should terminate the polling transaction and stop getting the event. Because if this time gets the event, then how to handle the event. Can only be discarded, and if the client initiates the request again, it will not be able to get the event.

The problem is, how to probe for client disconnects in HTTP handler. For example:

var incoming chan []byte
http. Handlefunc ("/polling", func (w http). Responsewriter, R *http. Request) {
    Select {case
    b: = <-incoming:
        w.write (b) Case
    <-time. After (5 * time. Second):
        w.write ("keepalive")
    //How to detect TCP disconnect event?
    }
)

There may be the following: Read R. Body, there should be an error if the disconnection is found. A friend takes reflect or hijack to the bottom tcpconn, and then peek. Converts W to http. Closenotifier, gets the event when the TCP connection is closed. r.body Read

This approach is not reliable, assuming that there is no body content, direct read detection is error:

Nn,err: = io. Copy (Ioutil. Discard, R.body)

The actual return is nn=0 and err=nil, i.e. no body, no error. Because the meaning of this read refers to the end of the request.

If you read the body and then read it. The IO is received. EOF, the request is over before the response is sent, so it is IO. EOF, and the underlying TCP disconnection cannot be detected. Peek Tcpconn

Using reflect to get the underlying Tcpconn object, is to know W http. Responsewriter is actually http.response:

A response represents the server side of an HTTP response.
Type response struct {
    conn             *conn

It has a field is conn, and then turn into Tcpconn can peek.

The risk is that different Golang versions may make changes to the underlying implementation and risk the upgrade.

The reflect approach is not always the best.

In addition, there is a way to use HTTP hijack mode, although this is the interface provided by the HTTP library, but many local comments say that hijack need special handling, and therefore is not the best way. Refer to If to use hijack. Close Notifier

The Http.closenotifier interface is provided in GO1.1, refer to close Notifier, but also note that there will be some problems, refer Net/http:closenotifier fails to the fire when underlying Connection is gone. Use the following:

var incoming chan []byte
http. Handlefunc ("/polling", func (w http). Responsewriter, R *http. Request) {
    Select {case
    <-W. (http. Closenotifier). Closenotify ():
        FMT. PRINTLN ("Connection closed")
    }
)

In fact, the timeout mechanism is always needed, plus the previous logic to consider the context. Context cancellation event, the complete implementation of Http-long polling should be:

func polling (CTX context. Context, incoming Chan []byte) {http. Handlefunc ("/polling", func (w http). Responsewriter, R *http. Request) {Select {case <-ctx. Done (): FMT. PRINTLN ("System quit") Case B: = <-Incoming:w.write (b) Case <-time. After (5 * time. Second): W.write ("keepalive") Case <-W. (http. Closenotifier). Closenotify (): FMT. PRINTLN ("Connection Closed")}})} 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.