http包server

littlexiaoshuishui發表於2021-07-18

只需要幾行程式碼就可以啟動http服務

func main()  {
    http.HandleFunc("/", sayHelloWorld) //路由處理, sayHelloWorld是函式變數, handler func(ResponseWriter, *Request)
    err := http.ListenAndServe(":9091", nil) //監聽9091埠
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

1.路由處理-ServeMux

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    es    []muxEntry // slice of entries sorted from longest to shortest.
    hosts bool       // whether any patterns contain hostnames
}
http包會有個全域性ServeMux,也就是DefaultServeMux,所以一般不用我們例項它
1.1註冊路由
type HandlerFunc func(ResponseWriter, *Request) //定義了函式類,這個類的變數都實現了介面http.Handler

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

func (mux *ServeMux) Handle(pattern string, handler Handler) {    
    e := muxEntry{h: handler, pattern: pattern}
    mux.m[pattern] = e    //實際註冊到ServeMux.m屬性中
}

2.服務物件-Serve

type Server struct {    
    Addr string
    Handler Handler // handler to invoke, http.DefaultServeMux if nil

    TLSConfig *tls.Config
    ReadTimeout time.Duration    
    ReadHeaderTimeout time.Duration    
    WriteTimeout time.Duration
    IdleTimeout time.Duration    
    MaxHeaderBytes int
    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

    ConnState func(net.Conn, ConnState)    
    ErrorLog *log.Logger
    BaseContext func(net.Listener) context.Context    
    ConnContext func(ctx context.Context, c net.Conn) context.Context
    inShutdown atomicBool // true when when server is in shutdown

    disableKeepAlives int32     // accessed atomically.
    nextProtoOnce     sync.Once // guards setupHTTP2_* init
    nextProtoErr      error     // result of http2.ConfigureServer if used

    mu         sync.Mutex
    listeners  map[*net.Listener]struct{}
    activeConn map[*conn]struct{}
    doneChan   chan struct{}
    onShutdown []func()
}
2.1.監聽埠
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler} //handler一開始是nil
    return server.ListenAndServe()
}

func (srv *Server) ListenAndServe() error {    
    addr := srv.Addr    
    ln, err := net.Listen("tcp", addr) //通過net監聽埠,net.listener
    return srv.Serve(ln)
}

func (srv *Server) Serve(l net.Listener) error {
    for {
        rw, err := l.Accept() //監聽到客戶端有連線,返回net.conn        
        c := srv.newConn(rw) //把net.conn封裝為http.conn
        go c.serve(connCtx) 
    }
}
2.2 連線物件-http.conn
type conn struct {

    server *Server
    cancelCtx context.CancelFunc
    rwc net.Conn
    remoteAddr string
    tlsState *tls.ConnectionState
    werr error

    // r is bufr's read source. It's a wrapper around rwc that provides
    // io.LimitedReader-style limiting (while reading request headers)
    // and functionality to support CloseNotifier. See *connReader docs.
    r *connReader

    // bufr reads from r.
    bufr *bufio.Reader

    // bufw writes to checkConnErrorWriter{c}, which populates werr on error.
    bufw *bufio.Writer

    // lastMethod is the method of the most recent request
    // on this connection, if any.
    lastMethod string

    curReq atomic.Value // of *response (which has a Request in it)

    curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState))

    // mu guards hijackedv
    mu sync.Mutex

    // hijackedv is whether this connection has been hijacked
    // by a Handler with the Hijacker interface.
    // It is guarded by mu.
    hijackedv bool
}
處理連線
func (c *conn) serve(ctx context.Context) {
    c.remoteAddr = c.rwc.RemoteAddr().String()
    c.r = &connReader{conn: c}
    c.bufr = newBufioReader(c.r)
    c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)

    for {
        w, err := c.readRequest(ctx) //獲取request物件,response物件
        c.curReq.Store(w)

        serverHandler{c.server}.ServeHTTP(w, w.req) //把requset,response交個路由器處理
        w.cancelCtx()        
        c.rwc.SetReadDeadline(time.Time{})
    }
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler //一開始listenAndServe時,Handler是nil.
    if handler == nil {
        handler = DefaultServeMux
    }    
    handler.ServeHTTP(rw, req) //最終交給DefaultServeMux處理
}
2.3.路由分發
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    h, _ := mux.Handler(r) //查詢路由獲取對應的HandlerFunc
    h.ServeHTTP(w, r)
}

3.1根據path獲取handler

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

返回http.Handler,註冊的函式都實現了http.Handler介面。

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
    host := stripHostPort(r.Host)
    path := cleanPath(r.URL.Path)
    return mux.handler(host, r.URL.Path)
}
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {    
    h, pattern = mux.match(path)
    return
}
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
    // Check for exact match first.
    v, ok := mux.m[path]
    if ok {
        return v.h, v.pattern
    }
    return nil, ""
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
用過哪些工具?為啥用這個工具(速度快,支援高併發...)?底層如何實現的?

相關文章