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

net/http/server.go部分代码的解释

2017-11-09 21:58 393 查看
写本次作业看了net/http一些函数,本篇博客主要解释一些我在练习或使用过的api。

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

用来注册路由,即,自行设置路由规则,pattern为URL的部分路径,handler为该路径对应的处理函数。当pattern为“/”时,默认匹配所有路劲。当request发送的URL,path可以匹配多个路由规则时,会把路径以树形的方式逐层进行匹配,“/”为根节点,最后优先匹配到路径最长的那个。

其中,DefaultServeMux,是ServeMux的一个默认实例。

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}


ServeMux

var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

type ServeMux struct {
mu    sync.RWMutex  // 读写锁
m     map[string]muxEntry  // 保存URL规则及其对应的处理函数
hosts bool // 用来判断是否决定pattern是否包含r.Host
}

type muxEntry struct {
explicit bool    // 用来标记pattern是否精确匹配
h        Handler // pattern对应的处理函数
pattern  string  // URL规则
}


func (mux *ServeMux) Handle(pattern string, handler Handler)

ServeMux的Handle对pattern合法性进行判断,若合法把pattern和对应的处理函数添加进默认路由

func (mux *ServeMux) Handle(pattern string, handler Handler) {
mux.mu.Lock()
defer mux.mu.Unlock()
// 判断pattern是否合法,pattern不能为空,为nil或一个pattern对应多个不同的handle函数
if pattern == "" {
panic("http: invalid pattern " + pattern)
}
if handler == nil {
panic("http: nil handler")
}
if mux.m[pattern].explicit {
panic("http: multiple registrations for " + pattern)
}
// 如果mux的map为空,需要分配一个map空间
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
// 把mux的map包装进新的pattern和其处理函数
mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}

// 如果不是“/”开头,则在请求的时候会以“host+path”一起放进match
if pattern[0] != '/' {
mux.hosts = true
}

// Helpful behavior:
// If pattern is /tree/, insert an implicit permanent redirect for /tree.
// It can be overridden by an explicit registration.
// 如果注册了一个路径“/tree/”但“/tree”没有被注册,那么“/tree”会被默认重定向到这个路由
n := len(pattern)
if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
// If pattern contains a host name, strip it and use remaining
// path for redirect.
path := pattern
if pattern[0] != '/' {
// In pattern, at least the last character is a '/', so
// strings.Index can't be -1.
path = pattern[strings.Index(pattern, "/"):]
}
url := &url.URL{Path: path}
mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}
}
}


func (srv *Server) Serve(l net.Listener) error

对某个端口进行监听,接收一个刚建立的连接,并发地对每个连接建立一个新服务对象,能够去读取每个连接请求并调用srv.Handler去回复这些请求。总是返回一个非空的error。

func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
if fn := testHookServerServe; fn != nil {
fn(srv, l)
}
var tempDelay time.Duration // 设置接收失败的延时时间

if err := srv.setupHTTP2_Serve(); err != nil {
return err
}

srv.trackListener(l, true)
defer srv.trackListener(l, false)

baseCtx := context.Background() // base is always background, per Issue 16220
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
// 在循环中accept,建立connetion,然后处理对应的connection
for {
rw, e := l.Accept()// 调用Accept监听
if e != nil {
select {
case <-srv.getDoneChan():
return ErrServerClosed
default:
}
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)

go c.serve(ctx)// 并发地处理请求
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  golang
相关文章推荐