Go标准包-http包server
http serve
只需要几行代码就可以启动http服务
func main() {
http.HandleFunc("/", sayHelloWorld) //路由处理, sayHelloWorld是函数变量, handler func(ResponseWriter, *Request)
err := http.ListenAndServe(":9091", nil) //监听9091端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
1.路由处理-ServeMux
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
http包会有个全局ServeMux,也就是DefaultServeMux,所以一般不用我们实例它
1.1注册路由
type HandlerFunc func(ResponseWriter, *Request) //定义了函数类,这个类的变量都实现了接口http.Handler
// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}
func (mux *ServeMux) Handle(pattern string, handler Handler) {
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e //实际注册到ServeMux.m属性中
}
2.服务对象-Serve
type Server struct {
Addr string
Handler Handler // handler to invoke, http.DefaultServeMux if nil
TLSConfig *tls.Config
ReadTimeout time.Duration
ReadHeaderTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
MaxHeaderBytes int
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
ConnState func(net.Conn, ConnState)
ErrorLog *log.Logger
BaseContext func(net.Listener) context.Context
ConnContext func(ctx context.Context, c net.Conn) context.Context
inShutdown atomicBool // true when when server is in shutdown
disableKeepAlives int32 // accessed atomically.
nextProtoOnce sync.Once // guards setupHTTP2_* init
nextProtoErr error // result of http2.ConfigureServer if used
mu sync.Mutex
listeners map[*net.Listener]struct{}
activeConn map[*conn]struct{}
doneChan chan struct{}
onShutdown []func()
}
2.1.监听端口
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler} //handler一开始是nil
return server.ListenAndServe()
}
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
ln, err := net.Listen("tcp", addr) //通过net监听端口,net.listener
return srv.Serve(ln)
}
func (srv *Server) Serve(l net.Listener) error {
for {
rw, err := l.Accept() //监听到客户端有连接,返回net.conn
c := srv.newConn(rw) //把net.conn封装为http.conn
go c.serve(connCtx)
}
}
2.2 连接对象-http.conn
type conn struct {
server *Server
cancelCtx context.CancelFunc
rwc net.Conn
remoteAddr string
tlsState *tls.ConnectionState
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.
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
curReq atomic.Value // of *response (which has a Request in it)
curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState))
// mu guards hijackedv
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
}
处理连接
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
c.r = &connReader{conn: c}
c.bufr = newBufioReader(c.r)
c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
for {
w, err := c.readRequest(ctx) //获取request对象,response对象
c.curReq.Store(w)
serverHandler{c.server}.ServeHTTP(w, w.req) //把requset,response交个路由器处理
w.cancelCtx()
c.rwc.SetReadDeadline(time.Time{})
}
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler //一开始listenAndServe时,Handler是nil.
if handler == nil {
handler = DefaultServeMux
}
handler.ServeHTTP(rw, req) //最终交给DefaultServeMux处理
}
2.3.路由分发
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
h, _ := mux.Handler(r) //查询路由获取对应的HandlerFunc
h.ServeHTTP(w, r)
}
3.1根据path获取handler
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
返回http.Handler,注册的函数都实现了http.Handler接口。
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
host := stripHostPort(r.Host)
path := cleanPath(r.URL.Path)
return mux.handler(host, r.URL.Path)
}
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
h, pattern = mux.match(path)
return
}
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
// Check for exact match first.
v, ok := mux.m[path]
if ok {
return v.h, v.pattern
}
return nil, ""
}
总结
1.ServeMux 等于srv.Handler,保存了路由map,实现了ServeHTTP()方法(conn会把w,r传到这个方法去),很多自定义http服务,都是重写srv.Handler
2.Serve 监听端口,管理连接
3.接口Handler 注册路由的函数必须实现这个接口,为了方便专门定义了一个类型HandlerFunc,只要是HandlerFunc类型的变量,就是实现了接口Handler
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
4.serverHandler 独立的结构,为了串联conn与srv.Handler
在conn连接对象中,接受的请求通过serverHandler{c.server}.ServeHTTP(w, w.req),最终handler.ServeHTTP()
区块链节点使用http包实现json-rpc功能
构造httpServer对象,作为srv.Handler. 连接对象会把w,r传给httpServer的ServeHTTP方法
func (h *httpServer) start() error {
h.server = &http.Server{Handler: h} //创建标准库srv, srv.Handler为httpServer
listener, err := net.Listen("tcp", h.endpoint)
h.listener = listener
go h.server.Serve(listener)
return nil
}
-------------------------------------------------
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
rpc := h.httpHandler.Load().(*rpcHandler) //这个是rpc.NewServer()创建的
rpc.ServeHTTP(w, r)//又转给rpcHandler
return
}
这里其实是多封装了一层,最终处理的Handler对象是rpc.NewServer(),所有这个rpcHandler等于标准库的srv.Handler,需要保存路由map,同时实现ServeHTTP方法。
本作品采用《CC 协议》,转载必须注明作者和本文链接