客户端和服务端
net/http
代码块分为客户端和服务端两个部分。以下是net/http标准库的各个组成部分在客户端/服务中的划分:
http包的执行过程
如下图
服务端和服务端通信的过程:
- 服务端创建
socket
,绑定/监听指定的ip地址和端口,即Listen Socket
- 客户端与
Listen Socket
连接,Listen Socket
接受客户端的请求,得到Client Socket
,接下来通过Client Socket
与客户端通信 - 创建
go
线程服务的一个连接,处理客户端的请求。首先从Client Socket
读取HTTP请求的协议头,如果是POST方法,还可能要读取客户端提交的数据。然后交给相应的handler
处理请求,handler
处理完毕准备好客户端需要的数据, 通过Client Socket
写给客户端
http服务器的执行过程
一个简单的服务器
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/hello", sayHello)
http.ListenAndServe(":8080", nil)
}
func sayHello(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "hello")
}
注册路由
首先查看http.HandleFunc("/hello", sayHello)
的源码:
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
继续查看DefaultServeMux
:
type ServeMux struct {
mu sync.RWMutex // 锁,由于请求涉及到并发处理,因此这里需要一个锁机制
m map[string]muxEntry //key是URL匹配字符串,muxEntry是对应的处理handler
hosts bool // 路由匹配时,是否包含host
}
type muxEntry struct {
h Handler // 这个路由表达式对应哪个handler
pattern string // 匹配字符串
}
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
return new(ServeMux) }
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
ServeMux
结构体:HTTP请求的多路转接器(路由),它负责将每一个接收到的请求的URL与一个注册模式的列表进行匹配,并调用和URL最匹配的模式的处理器。它内部用一个map来保存所有处理器Handler。
DefaultServeMux
,其实就是一个默认路由,是ServeMux
的一个实例,使用包级别的http.Handle()
、http.HandleFunc()
方法注册处理器时都是注册到该路由中。
再看DefaultServeMux.HandleFunc(pattern, handler)
中的HandleFunc
方法:
在HandleFunc
中调用ServerMux
的HandleFunc()
。将一个自定义的方法转换为一个一般Handler,最后再调用Server.Mux的handle()方法,完成URL与Handler的绑定,
// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
Handle
方法将相关信息加入到map
中:
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
// 加一个写锁
mux.mu.Lock()
defer mux.mu.</