Golang HTTP Server exploration (bottom)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In the previous article we passed:

func main() {    http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {        io.WriteString(w, "hello")    })    http.ListenAndServe(":9010", nil)}

The relationship between Http.handlefunc routing calls is analyzed. This. Let's analyze HTTP. Listenandserve ():

http.ListenAndServe(addr string, handler Handler)

The internal implementation of the function:

func ListenAndServe(addr string, handler Handler) error {    server := &Server{Addr: addr, Handler: handler}    return server.ListenAndServe()}

Discover this HTTP. Listenandserve actually calls the Server.listenandserve. Let's look at the structure of the server first:

type Server struct {    Addr         string        // TCP address to listen on, ":http" if empty    Handler      Handler       //处理器,如果为空则使用 http.DefaultServeMux     ReadTimeout  time.Duration     WriteTimeout time.Duration     ....}

See this handler, and then contact the last HTTP we analyzed. Handlefunc. We found that they were using HTTP by default. Defaultservemux this route processor. And in this processor we have just saved a route that we have registered. /hello. Then we look at the server. How the Listenandserve is listening and distributing routes.

func (srv *Server) ListenAndServe() error {    addr := srv.Addr    if addr == "" {        addr = ":http"    }    ln, err := net.Listen("tcp", addr)    if err != nil {        return err    }    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})}

In the server. Listenandserve registered a TCP listener, listening to our registered network port. Then continue calling

server.Serve(l net.Listener) error

For service.

func (srv *Server) Serve(l net.Listener) error {      .......    for {        rw, e := l.Accept()        ....        c := srv.newConn(rw)        c.setState(c.rwc, StateNew) // before Serve can return        go c.serve(ctx)    }}

Open a For loop and accept net.accept (). The Srv.newconn (net.conn) is then used to convert a TCP conn into a http.server#conn:

func (srv *Server) newConn(rwc net.Conn) *conn {    c := &conn{        server: srv,        rwc:    rwc,    }    ....    return c}

Finally, a go process is turned on to handle each request.

func (c *conn) serve(ctx context.Context) {       // 客户端主机ip    c.remoteAddr = c.rwc.RemoteAddr().String()        ....    // HTTP/1.x from here on.        //读取请求的数据    c.r = &connReader{r: c.rwc}    c.bufr = newBufioReader(c.r)    c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)    ctx, cancelCtx := context.WithCancel(ctx)    defer cancelCtx()    for {        w, err := c.readRequest(ctx)        ......        serverHandler{c.server}.ServeHTTP(w, w.req)        ...    }}

The request went down by seven, and finally entered:

serverHandler{c.server}.ServeHTTP(w, w.req)

and called the serverhandler.servehttp inside it. Decisive point open this function, enlightened, originally was called the topmost:

http.DefaultServeMux.Handle

Do not believe to look here:

type serverHandler struct {    srv *Server}func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {       //sh.srv.Handler =server.handler     handler := sh.srv.Handler    if handler == nil {               //我们最初传的参数就是 nil        handler = DefaultServeMux    }    if req.RequestURI == "*" && req.Method == "OPTIONS" {        handler = globalOptionsHandler{}    }    handler.ServeHTTP(rw, req)}

So, the final deal is that the function is the servemux.servehttpin the route, and last night we've analyzed what servemux.servehttp is doing with the function we passed in. After the server opens a request comes in, the first call is Server.servehttp (rw responsewriter, req *request).

func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {    .....    h, _ := mux.Handler(r)    h.ServeHTTP(w, r)}

The above function goes through Daoteng and finally goes to the Servemux#handler function:

func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {    mux.mu.RLock()    defer mux.mu.RUnlock()    // Host-specific pattern takes precedence over generic ones    if mux.hosts {        h, pattern = mux.match(host + path)    }    if h == nil {        h, pattern = mux.match(path)    }    if h == nil {        h, pattern = NotFoundHandler(), ""    }    return}

In this method, the URL is matched. The handle of the corresponding URL is returned on the match, otherwise it is called Notfoundhandler. Then call MuxEntry.h, which is the logical function of our custom processing.

Such a complete request HTTP request in the Golang inside of the flow process is very clear, is not it?

Attention Program Ape Public account:

Related Article

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.