您的位置:首页 > 理论基础 > 计算机网络

Go的http源码阅读笔记

2017-11-07 00:00 726 查看
Handler是Go实现http请求处理逻辑的入口,Handler是一个接口,该接口要求实现ServeHTTP方法。具体定义如下。

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

如果我们自定义了Handler的接口实现,便可以调用ListenAndServe函数进行http请求。

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

http.ListenAndServe封装了Server的ListenAndServe方法。

Server定义了运行http server的一些参数。

type Server struct {
Addr           string        // TCP address to listen on, ":http" if empty
Handler        Handler       // handler to invoke, http.DefaultServeMux if nil
ReadTimeout    time.Duration // maximum duration before timing out read of the request
WriteTimeout   time.Duration // maximum duration before timing out write of the response
MaxHeaderBytes int           // maximum size of request headers, DefaultMaxHeaderBytes if 0
TLSConfig      *tls.Config   // optional TLS config, used by ListenAndServeTLS

// TLSNextProto optionally specifies a function to take over
// ownership of the provided TLS connection when an NPN
// protocol upgrade has occurred.  The map key is the protocol
// name negotiated. The Handler argument should be used to
// handle HTTP requests and will initialize the Request's TLS
// and RemoteAddr if not already set.  The connection is
// automatically closed when the function returns.
// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

// ConnState specifies an optional callback function that is
// called when a client connection changes state. See the
// ConnState type and associated constants for details.
ConnState func(net.Conn, ConnState)

// ErrorLog specifies an optional logger for errors accepting
// connections and unexpected behavior from handlers.
// If nil, logging goes to os.Stderr via the log package's
// standard logger.
ErrorLog *log.Logger

disableKeepAlives int32     // accessed atomically.
nextProtoOnce     sync.Once // guards initialization of TLSNextProto in Serve
nextProtoErr      error
}

Server.ListenAndServe函数,监听addr中的tcp链接,并调用Serve函数。两个函数定义如下:

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)})
}

func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
if fn := testHookServerServe; fn != nil {
fn(srv, l)
}
var tempDelay time.Duration // how long to sleep on accept failure
if err := srv.setupHTTP2(); err != nil {
return err
}
for {
rw, e := l.Accept()
if e != nil {
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
time.Sleep(tempDelay)
continue
}
return e
}
tempDelay = 0
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
go c.serve()
}
}

在Accept处阻塞,直到有客户端连接,当请求到来时,Accept会从Listener l中接收一个到来的连接并创建一个新的goroutine处理请求。

其中,c := srv.newConn(rw) 是创建了一个http.conn。

// Create new connection from rwc.
func (srv *Server) newConn(rwc net.Conn) *conn {
c := &conn{
server: srv,
rwc:    rwc,
}
if debugServerConnections {
c.rwc = newLoggingConn("server", c.rwc)
}
return c
}

http.conn结构体如下:

type conn struct {
// server is the server on which the connection arrived.
// Immutable; never nil.
server *Server

// rwc is the underlying network connection.
// This is never wrapped by other types and is the value given out
// to CloseNotifier callers. It is usually of type *net.TCPConn or
// *tls.Conn.
rwc net.Conn

// remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously
// inside the Listener's Accept goroutine, as some implementations block.
// It is populated immediately inside the (*conn).serve goroutine.
// This is the value of a Handler's (*Request).RemoteAddr.
remoteAddr string

// tlsState is the TLS connection state when using TLS.
// nil means not TLS.
tlsState *tls.ConnectionState

// werr is set to the first write error to rwc.
// It is set via checkConnErrorWriter{w}, where bufw writes.
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.
// Users of bufr must hold mu.
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

// mu guards hijackedv, use of bufr, (*response).closeNotifyCh.
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
}

conn的serve中最重要的是serverHandler{c.server}.ServeHTTP(w, w.req)

// Serve a new connection.
func (c *conn) serve() {
c.remoteAddr = c.rwc.RemoteAddr().String()
defer func() {
... // defer处理
}()

... // tls connection

c.r = &connReader{r: c.rwc}
c.bufr = newBufioReader(c.r)
c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)

for {
w, err := c.readRequest() //读取请求
...
if err != nil {
....
return
}

...

// 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.
serverHandler{c.server}.ServeHTTP(w, w.req)

... // finish operation
}
}


// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}

serverHandler的ServeHTTP是真正调用我们自定义的Handler的ServeHTTP函数的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: