diff --git a/ebook/03.3.md b/ebook/03.3.md index bdae5bb4..a0beed81 100644 --- a/ebook/03.3.md +++ b/ebook/03.3.md @@ -59,19 +59,12 @@ Handler:处理请求和生成返回信息的处理逻辑 return e } tempDelay = 0 - if srv.ReadTimeout != 0 { - rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout)) - } - if srv.WriteTimeout != 0 { - rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout)) - } c, err := srv.newConn(rw) if err != nil { continue } go c.serve() } - panic("not reached") } 监控之后如何接收客户端的请求呢?上面代码执行监控端口之后,调用了`srv.Serve(net.Listener)`函数,这个函数就是处理接收客户端的请求信息。这个函数里面起了一个`for{}`,首先通过Listener接收请求,其次创建一个Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:`go c.serve()`。这个就是高并发体现了,用户的每一次请求都是在一个新的goroutine去服务,相互不影响。 diff --git a/ebook/03.4.md b/ebook/03.4.md index 6d824158..695de9a3 100644 --- a/ebook/03.4.md +++ b/ebook/03.4.md @@ -24,6 +24,7 @@ Go在等待客户端请求里面是这样写的: type ServeMux struct { mu sync.RWMutex //锁,由于请求涉及到并发处理,因此这里需要一个锁机制 m map[string]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式 + hosts bool // 是否在任意的规则中带有host信息 } 下面看一下muxEntry @@ -31,6 +32,7 @@ Go在等待客户端请求里面是这样写的: type muxEntry struct { explicit bool // 是否精确匹配 h Handler // 这个路由表达式对应哪个handler + pattern string //匹配字符串 } 接着看一下Handler的定义 @@ -48,25 +50,47 @@ Handler是一个接口,但是前一小节中的`sayhelloName`函数并没有 f(w, r) } -路由器里面存储好了相应的路由规则之后,那么具体的请求又是怎么分发的呢? +路由器里面存储好了相应的路由规则之后,那么具体的请求又是怎么分发的呢?请看下面的代码,默认的路由器实现了`ServeHTTP`: -路由器接收到请求之后调用`mux.handler(r).ServeHTTP(w, r)` + func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { + if r.RequestURI == "*" { + w.Header().Set("Connection", "close") + w.WriteHeader(StatusBadRequest) + return + } + h, _ := mux.Handler(r) + h.ServeHTTP(w, r) + } -也就是调用对应路由的handler的ServerHTTP接口,那么mux.handler(r)怎么处理的呢? +如上所示路由器接收到请求之后,如果是`*`那么关闭链接,不然调用`mux.Handler(r)`返回对应设置路由的处理Handler,然后执行`h.ServeHTTP(w, r)` - func (mux *ServeMux) handler(r *Request) Handler { +也就是调用对应路由的handler的ServerHTTP接口,那么mux.Handler(r)怎么处理的呢? + + func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { + if r.Method != "CONNECT" { + if p := cleanPath(r.URL.Path); p != r.URL.Path { + _, pattern = mux.handler(r.Host, p) + return RedirectHandler(p, StatusMovedPermanently), pattern + } + } + return mux.handler(r.Host, r.URL.Path) + } + + 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 - h := mux.match(r.Host + r.URL.Path) - if h == nil { - h = mux.match(r.URL.Path) + if mux.hosts { + h, pattern = mux.match(host + path) } if h == nil { - h = NotFoundHandler() + h, pattern = mux.match(path) } - return h + if h == nil { + h, pattern = NotFoundHandler(), "" + } + return } 原来他是根据用户请求的URL和路由器里面存储的map去匹配的,当匹配到之后返回存储的handler,调用这个handler的ServHTTP接口就可以执行到相应的函数了。