func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
func (srv *Server) ListenAndServe() error {
...
ln, err := net.Listen("tcp", addr)
...
return srv.Serve(ln)
}
func (srv *Server) Serve(l net.Listener) error {
...
// 将listener封装进server
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
for {
// 无限循环,accept接收客户端的请求
rw, err := l.Accept()
if err != nil {
select {
case <-srv.getDoneChan():
return ErrServerClosed
default:
}
if ne, ok := err.(net.Error); ok && ne.Temporary() {
... // 设置默认超时时间
time.Sleep(tempDelay)
continue
}
return err
}
// 封装accept到的连接,起一个goroutine来处理这个连接,之后继续等待accept的返回
connCtx := ctx
if cc := srv.ConnContext; cc != nil {
connCtx = cc(connCtx, rw)
...
}
tempDelay = 0
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
// 每次有连接进来都会起一个协程来处理
go c.serve(connCtx)
}
}
func (c *conn) serve(ctx context.Context) {
...
// 处理连接、tls处理之类的,从连接中读取数据,封装成request、response,交给serverHandler处理
...
if requestBodyRemains(req.Body) {
registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
} else {
// 该方法会起一个新协程在后台读取连接,就靠它来实现请求还没处理完就能进行取消的功能
// 实际上,取消后,只是连接被中断了,业务代码该执行还是在执行,执行完才能收到cancel信号
w.conn.r.startBackgroundRead()
}
// 默认的serverHandler.ServeHTTP方法会进行判断:
// 如果handler为空就会使用默认的DefaultServeMux,否则就用用户定义的ServeHTTP来处理请求
serverHandler{c.server}.ServeHTTP(w, w.req)
...
// 请求结束之后cancel掉context
w.cancelCtx()
}
// 处理连接时,处理会把连接交给serverHandler,还会起一个协程监控连接的状态
func (cr *connReader) startBackgroundRead() {
cr.lock()
defer cr.unlock()
...
cr.inRead = true
cr.conn.rwc.SetReadDeadline(time.Time{})
go cr.backgroundRead()
}
// 如果连接有问题,就会cancel掉
func (cr *connReader) backgroundRead() {
n, err := cr.conn.rwc.Read(cr.byteBuf[:])
cr.lock()
if n == 1 {
cr.hasByte = true
}
// 如果连接超时了,就会收到EOF的错误
if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {
} else if err != nil {
// 出错时就会触发cancel,从而结束掉请求
cr.handleReadError(err)
// handleReadError方法内就是下面这两句
// cr.conn.cancelCtx()
// cr.closeNotify()
}
cr.aborted = false
cr.inRead = false
cr.unlock()
cr.cond.Broadcast()
}
// DefaultServeMux的ServeHTTP方法,对请求进行路由匹配,用的就是http.HandleFunc里的map
// 根据path找到对应的handler,执行
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
}
// 获取注册的路由handler
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
// 路由handler的逻辑非常简单,就是直接根据path在map里匹配找到处理的handler
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
mux.mu.RLock()
defer mux.mu.RUnlock()
if mux.hosts {
h, pattern = mux.match(host + path)
}
if h == nil {
h, pattern = mux.match(path)
}
if h == nil {
h, pattern = NotFoundHandler(), ""
}
return
}
// 只是做简单的路由匹配
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
v, ok := mux.m[path]
if ok {
return v.h, v.pattern
}
for _, e := range mux.es {
if strings.HasPrefix(path, e.pattern) {
return e.h, e.pattern
}
}
return nil, ""
}