服务计算-net/http源码分析

net/http源码分析

一、构建一个简单的web服务器

如何用go实现一个最简单的http server呢?

package main

import (
    "fmt"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello World.")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":3000", nil)
}

这里的服务器只提供了根目录的路由功能。而HandleFunc与ListenAndServer作为http包最基础的函数是如何实现的呢?当然要看源码才能分析其中的奥秘。

二、http流程分析

http采用的client-server架构。client首先发送request到服务端,然后server接受request,根据路由处理并返回相应的response。最后client收到response以后会把相应的页面通过浏览器渲染出来。而这里我们主要对server端进行分析,那么server实现的功能是1.不断监听接收端口2.通过多路分解器处理request返回response也就对应了上述的两个函数。

三、http.HandleFunc

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

源码如上,它会调用DefaultServeMux的功能HandleFunc。而handler的定义是func(ResponseWriter, *Request)的。
接受request中最重要的就是用多路分解器(Multiplexer)实现路由功能了。Go有自己内置的mutilplexer -DefautServeMux,它是ServeMux结构的一个实例,并实现了Handler接口
ServeMux会使用handler并调用其ServeHTTP方法处理请求并返回响应。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

而 ServeHTTP 函数内部则会调用我们自定义的处理函数对客户端的请求信息进行处理。

四、http.ListenAndServe

func ListenAndServe(addr string, handler Handler) error {
  server := &Server{Addr: addr, Handler: handler}
  return server.ListenAndServe()
}

ListenAndServe源码如上,http.ListenAndServe 是先利用端口号和处理函数初始化一个 Server 结构实例,然后通过调用这个实例的 ListenAndServe() 来实现监听功能的。
server结构体如下:

type Server struct {
    Addr         string        
    Handler      Handler       
    ReadTimeout  time.Duration 
    WriteTimeout time.Duration 
    TLSConfig    *tls.Config   

    MaxHeaderBytes int

    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

    ConnState func(net.Conn, ConnState)
    ErrorLog *log.Logger
    disableKeepAlives int32     nextProtoOnce     sync.Once 
    nextProtoErr      error     
}

其中存储了服务器处理请求常见的字段。其中Handler字段也保留Handler接口。如果Server接口没有提供Handler结构对象,那么会使用DefautServeMux做multiplexer。
而Server的ListenAndServe功能如下。首先先用TCP搭建一个服务,然后监听设置的端口。

func (srv *Server) ListenAndServe() error {
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值