ListenAndServe閱讀web
func ListenAndServe(addr string, handler Handler) error { //1. 建立server server := &Server{Addr: addr, Handler: handler} //2. 啓動server return server.ListenAndServe() }
注意:建立一個server,啓動server,咱們也能夠按照這2個步驟去建立一個web服務安全
服務器
// 基類Closer接口,關閉全部連接中止服務 type Closer interface { Close() error } // 檢查服務是否存活,裏面定義了接口,接口的另類定義使用 // 奇怪的行爲,不肯定爲何這麼作 func http2h1ServerKeepAlivesDisabled(hs *Server) bool { var x interface{} = hs // 臨時定義接口,使用【奇怪的使用方法】 type I interface { doKeepAlives() bool } if hs, ok := x.(I); ok { return !hs.doKeepAlives() } return false } //Server // A Server defines parameters for running an HTTP server. // The zero value for Server is a valid configuration. type Server struct { Addr string // 監聽的TCP地址 Handler Handler // 註冊的路由處理方法 // 若是服務須要支持https協議 那麼須要相應的配置 TLSConfig *tls.Config //讀超時設置 ReadTimeout time.Duration // 讀取請求頭超時設置 ReadHeaderTimeout time.Duration // 寫超時 WriteTimeout time.Duration // 請求直接最長的空閒時長 IdleTimeout time.Duration // 請求頭最大的容量 MaxHeaderBytes int // HTTPS協議相關 TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // 能夠添回調函數,當客戶端處於哪一個狀態時候能夠執行某些動做 ConnState func(net.Conn, ConnState) // 錯誤日誌器,不設置默認使用內置logger模塊 ErrorLog *log.Logger //原子操做,是否保持長鏈接 disableKeepAlives int32 // accessed atomically. //原子操做,服務要關閉了 inShutdown int32 // accessed atomically (non-zero means we're in Shutdown) // https相關操做 用於初始化 nextProtoOnce sync.Once // guards setupHTTP2_* init nextProtoErr error // result of http2.ConfigureServer if used // 互斥鎖 保證資源的安全 mu sync.Mutex // 服務套接字表,監聽socket表 listeners map[*net.Listener]struct{} // 存活的客戶端連接表 activeConn map[*conn]struct{} //用於通知服務關閉了 doneChan chan struct{} // 註冊服務器關閉執行的一些行爲 onShutdown []func() }
注意:通常建立server只須要Addr與handler便可app
ListenAndServe閱讀socket
監聽並啓動服務tcp
func (srv *Server) ListenAndServe() error { // 判斷服務器是否是已經關閉了 if srv.shuttingDown() { return ErrServerClosed } // 獲取要綁定監聽的地址 addr := srv.Addr if addr == "" { addr = ":http" } // 建立用於監監聽socket連接 ln, err := net.Listen("tcp", addr) if err != nil { return err } // tcpKeepAliveListener 設置監聽超時,在accept的時不會一直阻塞 設置一個超時操做 //啓動服務 return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) }
srv.Serve源碼閱讀函數
func (srv *Server) Serve(l net.Listener) error { // 測試用的鉤子函數,其餘時候沒有用的 if fn := testHookServerServe; fn != nil { fn(srv, l) // call hook with unwrapped listener } // sync.once 建立一個once對象,用於防止屢次關閉連接 l = &onceCloseListener{Listener: l} // 結束的時候關閉監聽socket defer l.Close() // 設置http2相關的設置 if err := srv.setupHTTP2_Serve(); err != nil { return err } // 把監聽socket添加監聽表 if !srv.trackListener(&l, true) { return ErrServerClosed } // 結束的時候從監聽表刪除 defer srv.trackListener(&l, false) // 設置臨時過時時間,當accept發生 錯誤的時候等待一段時間 var tempDelay time.Duration // how long to sleep on accept failure // 設置context 主要用於取消任務 baseCtx := context.Background() // base is always background, per Issue 16220 // 注意ctx把server自己傳遞進去了,用於傳遞 ctx := context.WithValue(baseCtx, ServerContextKey, srv) // 循環監聽客戶端到來 for { // accept 阻塞等待客戶單到來 rw, e := l.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 tempDelay = 0 // 建立server鏈接,server鏈接包含了與客戶端通信的socket以及server相關的信息 c := srv.newConn(rw) // 更新連接狀態 c.setState(c.rwc, StateNew) // before Serve can return // 啓動goroutine處理socket go c.serve(ctx) } }
server conn結構體閱讀post
// 服務端連接結構體 type conn struct { // 連接綁定服務 server *Server // 用於取消任務的ctxFunc cancelCtx context.CancelFunc // socket 通信用的底層socket rwc net.Conn // 客戶端地址127.0.0.0:5678 remoteAddr string // tls 狀態 tlsState *tls.ConnectionState // werr is set to the first write error to rwc. // 第一次寫出現錯誤的時候設置 werr error // r is bufr's read source. // 用於讀取請求的對象,主要用於讀取數據的 r *connReader // bufr reads from r. // r讀取的數據存儲buf bufr *bufio.Reader // bufw writes to checkConnErrorWriter{c}, which populates werr on error. // 寫buf bufw *bufio.Writer // lastMethod is the method of the most recent request // on this connection, if any. // 最後一次請求,方法 是post仍是其餘等 lastMethod string // 當前的請求 curReq atomic.Value // of *response (which has a Request in it) // 當前cnn狀態 curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState)) //保護hijackedv mu sync.Mutex // hijackedv is whether this connection has been hijacked //表示是否支持用戶劫持連接【主要用於切換協議的】 hijackedv bool }