Go网络编程之net/http包执行流程源码分析
来源:互联网 发布:java sleep释放锁吗 编辑:程序博客网 时间:2024/06/09 20:25
1. http包建立web服务器
package mainimport ( "fmt" "log" "net/http" "strings")func sayhelloName(w http.ResponseWriter, r *http.Request) { r.ParseForm() fmt.Println(r.Form) fmt.Println("path", r.URL.Path) fmt.Println("scheme", r.URL.Scheme) fmt.Println(r.Form["url_long"]) for k, v := range r.Form { fmt.Println("key:", k) fmt.Println("val:", strings.Join((v), "")) } fmt.Println(w, "hello world")}func main() { http.HandleFunc("/", sayhelloName) err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal("ListenAndServe:", err) }}
2. http包的运行机制
相关源码位于:/src/net/http/server.go
服务端的几个概念
- Request:用户请求的信息,用来解析用户的请求信息,包括post,get,Cookie,url等信息。
- Response:服务器需要反馈给客户端的信息。
- Conn:用户的每次请求链接。
- Handle:处理请求和生成返回信息的处理逻辑。
Go实现web服务的流程
- 创建Listen Socket,监听指定的端口,等待客户端请求到来。
- Listen Socket接受客户端的请求,得到Client Socket,接下来通过Client Socket与客户端通信。
- 处理客户端请求,首先从Client Socket读取HTTP请求的协议头,如果是POST方法,还可能要读取客户端提交的数据,然后交给相应的handler处理请求,handler处理完,将数据通过Client Socket返回给客户端。
2.1. http包执行流程图
2.2. 注册路由[HandleFunc]
http.HandlerFunc类型默认实现了ServeHTTP的接口。
// The HandlerFunc type is an adapter to allow the use of// ordinary functions as HTTP handlers. If f is a function// with the appropriate signature, HandlerFunc(f) is a// Handler that calls f.type HandlerFunc func(ResponseWriter, *Request)// ServeHTTP calls f(w, r).func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r)}
// HandleFunc registers the handler function for the given pattern// in the DefaultServeMux.// The documentation for ServeMux explains how patterns are matched.func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, 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))}
Handle
2.3. 如何监听端口
通过ListenAndServe来监听,底层实现:初始化一个server对象,调用net.Listen("tcp",addr),也就是底层用TCP协议搭建了一个服务,监听设置的端口。然后调用srv.Serve(net.Listener)函数,这个函数处理接收客户端的请求信息。这个函数里起了一个for循环,通过Listener接收请求,创建conn,开一个goroutine,把请求的数据当作参数给conn去服务:go c.serve(),即每次请求都是在新的goroutine中去服务,利于高并发。
2.4. 如何接收客户端的请求
srv.Serve
关键代码:
newConn
2.5. 如何分配handler
conn先解析request:c.readRequest(),获取相应的handler:handler:=c.server.Handler,即ListenAndServe的第二个参数,因为值为nil,所以默认handler=DefaultServeMux。该变量是一个路由器,用来匹配url跳转到其相应的handle函数。其中http.HandleFunc("/",sayhelloName)即注册了请求“/”的路由规则,当uri为“/”时,路由跳转到函数sayhelloName。DefaultServeMux会调用ServeHTTP方法,这个方法内部调用sayhelloName本身,最后写入response的信息反馈给客户端。
2.5.1. c.serve()
2.5.2. c.readRequest()
2.5.3. ServeHTTP(w, w.req)
2.5.4. DefaultServeMux
handler接口的定义
2.5.5. ServeMux.ServeHTTP
mux.Handler(r)
2.6. http连接处理流程图
3. http的执行流程总结
1、首先调用Http.HandleFunc,按如下顺序执行:
- 调用了DefaultServerMux的HandleFunc。
- 调用了DefaultServerMux的Handle。
- 往DefaultServerMux的map[string] muxEntry中增加对应的handler和路由规则。
2、调用http.ListenAndServe(":9090",nil),按如下顺序执行:
- 实例化Server。
- 调用Server的ListenAndServe()。
- 调用net.Listen("tcp",addr)监听端口。
- 启动一个for循环,在循环体中Accept请求。
- 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()。
- 读取每个请求的内容w,err:=c.readRequest()。
- 判断handler是否为空,如果没有设置handler,handler默认设置为DefaultServeMux。
- 调用handler的ServeHttp。
- 根据request选择handler,并且进入到这个handler的ServeHTTP,
mux.handler(r).ServeHTTP(w,r) - 选择handler
- 判断是否有路由能满足这个request(循环遍历ServeMux的muxEntry)。
- 如果有路由满足,调用这个路由handler的ServeHttp。
- 如果没有路由满足,调用NotFoundHandler的ServeHttp。
4. 自定义路由
Go支持外部实现路由器,ListenAndServe的第二个参数就是配置外部路由器,它是一个Handler接口。即外部路由器实现Hanlder接口。
Handler接口:
自定义路由
文章参考:
《Go web编程》
- Go网络编程之net/http包执行流程源码分析
- Go源码分析 net/http包分析:追溯到socket
- Go Web编程:http包分析
- Go网络编程之HTTP编程
- Go net/http包
- Go搭建简单服务器及http包源码分析
- go语言net/http包解析http body之坑
- angularjs源码分析之:angularjs执行流程
- angularjs源码分析之:angularjs执行流程
- springmvc----源码分析之springmvc执行流程
- go语言 通过http包搭建简单web服务器 对http包源码的略微分析
- Nginx源码分析—HTTP框架执行流程
- Nginx源码分析—HTTP框架执行流程
- Nginx源码分析—HTTP框架执行流程
- Go语言学习之net/http包(The way to go)
- Golang中net/http包源码分析与解释
- Go语言备忘录:net/http包的使用模式和源码解析
- redis执行流程源码分析
- 强制清除 gradle 依赖缓存
- 框架学习之struts2-01主要配置
- 爬虫实战6—分布式系统设计
- 西西里1007
- 利用 Jekyll + Github pages 搭建个人博客
- Go网络编程之net/http包执行流程源码分析
- D
- 前端面试题(1)
- 矩阵快速幂模板
- Spring@Autowired注解与自动装配
- SQL update select结合语句详解及应用
- SET NOCOUNT ON
- 窗体的常用属性及设置
- MySQL主备环境切换