golang 建立web服务器 http包源码详解
首先,熟悉http协议的都知道,http协议是基于TCP实现的。
http服务器的工作方式大概就是监听socket端口,接受连接,获取到请求,处理请求,返回响应。
所以,对应的会有几个部分
Request:用户请求的信息。post、get、url等这些信息
Response: 返回给客户端的信息
Conn: 用户每次的连接请求
Handler:处理请求和返回信息的逻辑处理
1. 搭建简单的web服务器
用golang可以很快地建立一个Web服务器
// httpWeb project main.go
package main
import (
"fmt"
"log"
"net/http"
"strings"
)
func HandleRequest(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["bookId"])
for k, v := range r.Form {
fmt.Printf("key: %s, value: %s \n", k, strings.Join(v, " "))
}
fmt.Fprintf(w, "Respone message: Server get bookId successed....")
}
func main() {
http.HandleFunc("/", HandleRequest)
err := http.ListenAndServe(":6666", nil)
if err != nil {
log.Fatal("ListenError:", err)
}
}
当输入 localhost:6060/?bookId=2222&bookId=6666 ,就会连接到该服务器,效果如下:
服务接收请求。至于二次请求favicon.ico的问题暂不讨论。
这样子,简单的一个web服务器就可以运行,处理简单的用户请求。
2. http包源码探究
只是这样子知道怎么搭起一个web服务器并不能满足对技术的好奇心
想要了解简单的几行代码是如何就建立起一web服务器的?
最好的方法就是直接读源代码,让代码来告诉我们实现的原理
回到一开始的web服务器,仔细想想,基本上是两个函数撑起整个Web服务器啊!
居然如此简洁!!
http.HandleFunc("/", HandleRequest)
http.ListenAndServe(":6666", nil)
不难理解,大概就是处理请求的函数,和监听端口。
首先,先分析一下http.HandleFunc()
这个函数。
直接进入函数HandleFunc
的声明,源码如下
// 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)
}
这里DefaultServeMux调用了HandleFunc()
参数就是传进来的“/”
和HandleFunc
(定义一个函数类型,就可以把函数作为参数传入)
对于DefaultServeMux在源代码中的声明如下
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
type muxEntry struct {
explicit bool
h Handler
pattern string
}
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
return &ServeMux{m: make(map[string]muxEntry)}
}
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = NewServeMux()
可以看到,DefaultServeMux是一个默认的ServerMux,而ServeMux的结构体中,mu sync.RWMutex
是一个并发控制的锁,一个装有muxEntry结构的map,一个hosts判断是否包含主机名。
!!!仔细一看,这个muxEntry结构体,其中一个变量h Handler
和另一个变量pattern string
。
而这个Handler定义如下
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
是一个接口!!方法是ServeHTTP(ResponseWriter, *Request)
。
总结一下
DefaultServeMux的代码看完,大概清楚了。DefaultServeMux是一个ServerMux结构,这个结构里面最最主要包含一个map[string]muxEntry,map里面的每个muxEntry又包含一个string类型的变量pattern和一个接口Handler,这个接口里面的方法是ServeHTTP(ResponseWriter, *Request)。
好了,了解完DefaultServeMux,继续进入它调用的函数。
// HandleFunc registers the handler function for the given patter