美文网首页
net.http (服务端)

net.http (服务端)

作者: 个00个 | 来源:发表于2019-04-22 11:05 被阅读0次

    golang的http服务包 , 包括服务端和客户端

    package main
    
    import (
        "net/http"
        "fmt"
    )
    
    func HandConn(w http.ResponseWriter, r *http.Request) {
        fmt.Println(r.Host)
        fmt.Println(r.Method)
        fmt.Println(r.URL)
        w.Write([]byte("hello go"))
    }
    
    func main() {
        // 注册处理函数
        http.HandleFunc("/", HandConn)
    
        // 启动
        http.ListenAndServe(":8080", nil)
    }
    

    这样就创建了一个http的Server. 真简单呢.

    1. 服务启动
    // ListenAndServe always returns a non-nil error.
    func ListenAndServe(addr string, handler Handler) error {
        server := &Server{Addr: addr, Handler: handler}             // 这个 handler 是用来处理 connections 的
        return server.ListenAndServe()    
    }
    
    1. 建立连接之后再goroutine里处理
    //  go c.serve(ctx)
    
    // Serve a new connection.
    func (c *conn) serve(ctx context.Context) {
        c.remoteAddr = c.rwc.RemoteAddr().String()        // 远程地址.
        ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())  // 本地地址
        defer func() {...}() //先不看这个
    
        if tlsConn, ok := c.rwc.(*tls.Conn); ok {...} // 先过滤https的请求? 还是http2的请求.? 
    
        // HTTP/1.x from here on.
    
        ctx, cancelCtx := context.WithCancel(ctx)
        c.cancelCtx = cancelCtx   // 塞入取消方法. 参考 context.
        defer cancelCtx()
    
        c.r = &connReader{conn: c}
        c.bufr = newBufioReader(c.r)                 //  初始化读buf
        c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)   // 初始化写buf
    
            //// 大大的死循环.
        for {
            w, err := c.readRequest(ctx)      // 读...  req, err := readRequest(c.bufr, keepHostHeader)
            if c.r.remain != c.server.initialReadLimitSize() {
                // If we read any bytes off the wire, we're active.
                c.setState(c.rwc, StateActive)   // 读到数据变更状态 
            }
            if err != nil {...} // 读出失败的处理
    
            // Expect 100 Continue support
            req := w.req
            if req.expectsContinue() {
                if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
                    // Wrap the Body reader with one that replies on the connection
                    req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
                }
            } else if req.Header.get("Expect") != "" {
                w.sendExpectationFailed()
                return
            }
    
            c.curReq.Store(w)   // 把req存起来.
    
            if requestBodyRemains(req.Body) {
                registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
            } else {
                w.conn.r.startBackgroundRead()
            }
    
            // HTTP cannot have multiple simultaneous active requests.[*]
            // Until the server replies to this request, it can't read another,
            // so we might as well run the handler in this goroutine.
            // [*] Not strictly true: HTTP pipelining. We could let them all process
            // in parallel even if their responses need to be serialized.
            // But we're not going to implement HTTP pipelining because it
            // was never deployed in the wild and the answer is HTTP/2.
            serverHandler{c.server}.ServeHTTP(w, w.req)       // 处理...  DefaultServeMux
            w.cancelCtx()  // 关闭刚刚的协程. 
            if c.hijacked() {
                return
            }
            w.finishRequest()
            if !w.shouldReuseConnection() {
                if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
                    c.closeWriteAndWait()
                }
                return
            }
            c.setState(c.rwc, StateIdle)      //  再次改变状态 ... 到空闲.
            c.curReq.Store((*response)(nil))
    
            if !w.conn.server.doKeepAlives() {
                // We're in shutdown mode. We might've replied
                // to the user without "Connection: close" and
                // they might think they can send another
                // request, but such is life with HTTP/1.1.
                return
            }
    
            if d := c.server.idleTimeout(); d != 0 {           // 如果设置了空闲时间则. 等待.
                c.rwc.SetReadDeadline(time.Now().Add(d))
                if _, err := c.bufr.Peek(4); err != nil {
                    return
                }
            }
            c.rwc.SetReadDeadline(time.Time{})    // 设置了读的结束时间.
        }
    }
    
    默认的处理器.
    // DefaultServeMux is the default ServeMux used by Serve.
    // var DefaultServeMux = &defaultServeMux
    
    // ServeHTTP dispatches the request to the handler whose
    // pattern most closely matches the request URL.
    func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
        if r.RequestURI == "*" {
            if r.ProtoAtLeast(1, 1) {
                w.Header().Set("Connection", "close")
            }
            w.WriteHeader(StatusBadRequest)
            return
        }
        h, _ := mux.Handler(r)   // 其实是执行了 Handler  // 根据host得到匹配的 h.
        h.ServeHTTP(w, r)
    }
    
    

    echo框架的核心就是替换了 Handle 不在使用默认的 Handle ... 进而有了自己的路由规则.

    相关文章

      网友评论

          本文标题:net.http (服务端)

          本文链接:https://www.haomeiwen.com/subject/xhdcgqtx.html