net.http (服务端)

2019-04-22  本文已影响0人  个00个

golang的http服务包 , 包括服务端和客户端

package main

import (
    "net/http"
    "fmt"
)

func HandConn(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Host)
    fmt.Println(r.Method)
    fmt.Println(r.URL)
    w.Write([]byte("hello go"))
}

func main() {
    // 注册处理函数
    http.HandleFunc("/", HandConn)

    // 启动
    http.ListenAndServe(":8080", nil)
}

这样就创建了一个http的Server. 真简单呢.

  1. 服务启动
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}             // 这个 handler 是用来处理 connections 的
    return server.ListenAndServe()    
}
  1. 建立连接之后再goroutine里处理
//  go c.serve(ctx)

// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
    c.remoteAddr = c.rwc.RemoteAddr().String()        // 远程地址.
    ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())  // 本地地址
    defer func() {...}() //先不看这个

    if tlsConn, ok := c.rwc.(*tls.Conn); ok {...} // 先过滤https的请求? 还是http2的请求.? 

    // HTTP/1.x from here on.

    ctx, cancelCtx := context.WithCancel(ctx)
    c.cancelCtx = cancelCtx   // 塞入取消方法. 参考 context.
    defer cancelCtx()

    c.r = &connReader{conn: c}
    c.bufr = newBufioReader(c.r)                 //  初始化读buf
    c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)   // 初始化写buf

        //// 大大的死循环.
    for {
        w, err := c.readRequest(ctx)      // 读...  req, err := readRequest(c.bufr, keepHostHeader)
        if c.r.remain != c.server.initialReadLimitSize() {
            // If we read any bytes off the wire, we're active.
            c.setState(c.rwc, StateActive)   // 读到数据变更状态 
        }
        if err != nil {...} // 读出失败的处理

        // Expect 100 Continue support
        req := w.req
        if req.expectsContinue() {
            if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
                // Wrap the Body reader with one that replies on the connection
                req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
            }
        } else if req.Header.get("Expect") != "" {
            w.sendExpectationFailed()
            return
        }

        c.curReq.Store(w)   // 把req存起来.

        if requestBodyRemains(req.Body) {
            registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
        } else {
            w.conn.r.startBackgroundRead()
        }

        // HTTP cannot have multiple simultaneous active requests.[*]
        // Until the server replies to this request, it can't read another,
        // so we might as well run the handler in this goroutine.
        // [*] Not strictly true: HTTP pipelining. We could let them all process
        // in parallel even if their responses need to be serialized.
        // But we're not going to implement HTTP pipelining because it
        // was never deployed in the wild and the answer is HTTP/2.
        serverHandler{c.server}.ServeHTTP(w, w.req)       // 处理...  DefaultServeMux
        w.cancelCtx()  // 关闭刚刚的协程. 
        if c.hijacked() {
            return
        }
        w.finishRequest()
        if !w.shouldReuseConnection() {
            if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
                c.closeWriteAndWait()
            }
            return
        }
        c.setState(c.rwc, StateIdle)      //  再次改变状态 ... 到空闲.
        c.curReq.Store((*response)(nil))

        if !w.conn.server.doKeepAlives() {
            // We're in shutdown mode. We might've replied
            // to the user without "Connection: close" and
            // they might think they can send another
            // request, but such is life with HTTP/1.1.
            return
        }

        if d := c.server.idleTimeout(); d != 0 {           // 如果设置了空闲时间则. 等待.
            c.rwc.SetReadDeadline(time.Now().Add(d))
            if _, err := c.bufr.Peek(4); err != nil {
                return
            }
        }
        c.rwc.SetReadDeadline(time.Time{})    // 设置了读的结束时间.
    }
}
默认的处理器.
// DefaultServeMux is the default ServeMux used by Serve.
// var DefaultServeMux = &defaultServeMux

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    if r.RequestURI == "*" {
        if r.ProtoAtLeast(1, 1) {
            w.Header().Set("Connection", "close")
        }
        w.WriteHeader(StatusBadRequest)
        return
    }
    h, _ := mux.Handler(r)   // 其实是执行了 Handler  // 根据host得到匹配的 h.
    h.ServeHTTP(w, r)
}

echo框架的核心就是替换了 Handle 不在使用默认的 Handle ... 进而有了自己的路由规则.

上一篇下一篇

猜你喜欢

热点阅读