【简单的HTTP服务器】
源文件中 ListenAndServe()函数的注释中有个简单的HTTP服务实现代码,如下
package main
import (
"io"
"log"
"net/http"
)
func HelloServer(w , r *) {
(w, "hello ,this is from HelloServer func ")
}
func main() {
("/hello", HelloServer)
((":12345", nil))
}
通过浏览器 或者命令行工具可以访问
lynx localhost:12345/hello
【】
()源码如下
// ListenAndServe listens on the TCP network address addr
// and then calls Serve with handler to handle requests
// on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
// Handler is typically nil, in which case the DefaultServeMux is
// used.
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return ()
}
首先创建了一个 Server类型的数据,通过addr 和handler 来初始化。然后调用Server类型的成员函数 ListenAndServe()。
Server类型的定义如下,主要定义了http的一些参数,默认可为0.如上图,只初始化了 Addr 和Handler成员。
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
Handler Handler // handler to invoke, if nil
TLSConfig * // optional TLS config, used by ServeTLS and ListenAndServeTLS
// ReadTimeout is the maximum duration for reading the entire
// request, including the body.
//
// Because ReadTimeout does not let Handlers make per-request
// decisions on each request body's acceptable deadline or
// upload rate, most users will prefer to use
// ReadHeaderTimeout. It is valid to use them both.
ReadTimeout
// ReadHeaderTimeout is the amount of time allowed to read
// request headers. The connection's read deadline is reset
// after reading the headers and the Handler can decide what
// is considered too slow for the body.
ReadHeaderTimeout
// WriteTimeout is the maximum duration before timing out
// writes of the response. It is reset whenever a new
// request's header is read. Like ReadTimeout, it does not
// let Handlers make decisions on a per-request basis.
WriteTimeout
// IdleTimeout is the maximum amount of time to wait for the
// next request when keep-alives are enabled. If IdleTimeout
// is zero, the value of ReadTimeout is used. If both are
// zero, ReadHeaderTimeout is used.
IdleTimeout
// MaxHeaderBytes controls the maximum number of bytes the
// server will read parsing the request header's keys and
// values, including the request line. It does not limit the
// size of the request body.
// If zero, DefaultMaxHeaderBytes is used.
MaxHeaderBytes int
// TLSNextProto optionally specifies a function to take over
// ownership of the provided TLS connection when an NPN/ALPN
// protocol upgrade has occurred. The map key is the protocol
// name negotiated. The Handler argument should be used to
// handle HTTP requests and will initialize the Request's TLS
// and RemoteAddr if not already set. The connection is
// automatically closed when the function returns.
// If TLSNextProto is not nil, HTTP/2 support is not enabled
// automatically.
TLSNextProto map[string]func(*Server, *, Handler)
// ConnState specifies an optional callback function that is
// called when a client connection changes state. See the
// ConnState type and associated constants for details.
ConnState func(, ConnState)
// ErrorLog specifies an optional logger for errors accepting
// connections and unexpected behavior from handlers.
// If nil, logging goes to via the log package's
// standard logger.
ErrorLog *
// Has unexported fields.
}
通过 go doc Server 命令 还可以快速看到Server类型的成员函数
func (srv *Server) Close() error
func (srv *Server) ListenAndServe() error
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error
func (srv *Server) RegisterOnShutdown(f func())
func (srv *Server) Serve(l ) error
func (srv *Server) ServeTLS(l , certFile, keyFile string) error
func (srv *Server) SetKeepAlivesEnabled(v bool)
func (srv *Server) Shutdown(ctx ) error
Server类型的ListenAndServe()源码如下
2627 func (srv *Server) ListenAndServe() error {
2628 addr :=
2629 if addr == "" {
2630 addr = ":http"
2631 }
2632 ln, err := ("tcp", addr)
2633 if err != nil {
2634 return err
2635 }
2636 return (tcpKeepAliveListener{ln.(*)})
2637 }
首先获取其成语的 Addr,即ip port, 然后调用() 函数,实现端口监听。
在返回 Server类型的Serve成员方法时,有个 tcpKeepAliveListener{ln.(*)} 操作。其中tcpKeepAliveListener 类型的源码如下,只有一个 Accept()成员方法。通过TCPListener 类型的AcceptTCP()成员方法返回 *TCPConn类型数据,然后调用*TCPConn的成员方法SetKeepAlive() 来开启超时时间的设置。
3115 type tcpKeepAliveListener struct {
3116 *
3117 }
3118
3119 func (ln tcpKeepAliveListener) Accept() (c , err error) {
3120 tc, err := ()
3121 if err != nil {
3122 return
3123 }
3124 (true)
3125 (3 * )
3126 return tc, nil
3127 }
回到 Server 类型的ListenAndServe()方法的源码 return (tcpKeepAliveListener{ln.(*)})。(ln.(*)为类型断言语句)。Server类型的Serve方法,源码如下。
2678 func (srv *Server) Serve(l ) error {
2679 defer ()
2680 if fn := testHookServerServe; fn != nil {
2681 fn(srv, l)
2682 }
2683 var tempDelay // how long to sleep on accept failure
2684
2685 if err := srv.setupHTTP2_Serve(); err != nil {
2686 return err
2687 }
2688
2689 (l, true)
2690 defer (l, false)
2691
2692 baseCtx := () // base is always background, per Issue 16220
2693 ctx := (baseCtx, ServerContextKey, srv)
2694 for {
2695 rw, e := ()
2696 if e != nil {
2697 select {
2698 case <-():
2699 return ErrServerClosed
2700 default:
2701 }
2702 if ne, ok := e.(); ok && () {
2703 if tempDelay == 0 {
2704 tempDelay = 5 *
2705 } else {
2706 tempDelay *= 2
2707 }
2708 if max := 1 * ; tempDelay > max {
2709 tempDelay = max
2710 }
2711 ("http: Accept error: %v; retrying in %v", e, tempDelay)
2712 (tempDelay)
2713 continue
2714 }
2715 return e
2716 }
2717 tempDelay = 0
2718 c := (rw)
2719 (, StateNew) // before Serve can return
2720 go (ctx)
2721 }
2722 }
代码很长且逻辑较多,我们暂且简化下,先梳理大体的逻辑,后续再展开研究。大量精简后的代码如下
2678 func (srv *Server) Serve(l ) error {
2679 defer ()
2694 for {
2695 rw, e := ()
2716 }
2718 c := (rw)
2720 go (ctx)
2721 }
2722 }
即 主体通过一个for循环,通过Accept方法监听请求,收到请求后创建一个新的conn类型数据 ,然后通过go cserver() 实现并发处理。处理完请求后 通过defer () 回收资源。
到此大致梳理完了 ()的基本逻辑。回到文字开头的代码 (":12345", nil)
1、执行ListenAndServe(":12345",nil)后,会创建一个Server类型数据。
2、通过“:12345” 来初始化 Server的 Addr成员。Handler成员为nil
3、调用Server类型的成员函数ListenAndServe()。并通过未导出的tcpKeepAliveListener 类型做了接口转换。
tcpKeepAliveListener类型即*,用于超时时间的设定
4、调用Server类型的Serve方法,实现接口的监听 及并发处理请求。
即httpListenAndServe()函数 封装了 底层TCP通信的实现逻辑。