This article Csdn blog links: http://blog.csdn.net/screscent/article/details/53583764
This article QQ space link: http://user.qzone.qq.com/29185807/blog/1481529299 golang-net/http Source Code Analysis of HTTP Server 1 Introduction
Look at the example in the Net/http library first
To create an HTTP server, just a few simple statements.
http. Handle ("/foo", Foohandler)
http. Handlefunc ("/bar", func (w http). Responsewriter, R *http. Request) {
fmt. fprintf (W, "Hello,%q", HTML.) Escapestring (R.url. Path)
})
log. Fatal (http. Listenandserve (": 8080", nil))
The interface section is as follows
Type Handlerfunc func (Responsewriter, *request)
2 Routing
To understand HTTP server, you should start with routing. So start looking at the source
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 new (SERVEMUX)}
//Defaultservemux are the default Servemux used by Serve.
var Defaultservemux = &defaultservemux
Servermux is an HTTP routing struct. The map inside contains a routing hash table.
In addition, the above code also forms a Defaultservemux, the default routing object.
Type Servemux
func newservemux () *servemux
func (mux *servemux) Handle (pattern string, handler handler)
Func (Mux *servemux) Handlefunc (pattern string, handler func (Responsewriter, *request))
func (Mux *servemux) handler (R *request) (H Handler, pattern string)
Func (Mux *servemux) servehttp (w responsewriter, R *request)
The following one to do function Analysis 2.1 Handle
Func (Mux *servemux) Handle (pattern string, handler handler)
This function is to register the routing table function, the function is to create the muxentry, and then put it into the routing map
Func (Mux *servemux) Handle (pattern string, handler handler) {Mux.mu.Lock () defer Mux.mu.Unlo CK () if pattern = = "" {Panic ("http:invalid pattern" + pattern)} I
F handler = = nil {Panic ("Http:nil handler")} if mux.m[pattern].explicit {
Panic ("Http:multiple registrations for" + pattern)} if mux.m = = Nil { MUX.M = Make (Map[string]muxentry)}//main place is here mux.m[pattern] = Muxentry{explici
T:true, H:handler, Pattern:pattern} if pattern[0]!= '/' {mux.hosts = true}
Helpful behavior://If is/tree/, insert an implicit permanent redirect.
It can be overridden by a explicit registration. N: = Len (pattern) if n > 0 && pattern[n-1] = = '/' &&!mux.m[pattern[0:n-1]].explicit {//If contains a host name, strip it and use remain
ing//path for redirect. Path: = Pattern if pattern[0]!= '/' {//in pattern, at least the last character is a '/', so//strings.
Index can ' t be-1. Path = pattern[strings. Index (Pattern, "/"):]} URL: = &url. Url{path:path} mux.m[pattern[0:n-1] = Muxentry{h:redirecthandler (URL. String (), statusmovedpermanently), Pattern:pattern}}}
2.2 Handlefunc
Handlefunc is the encapsulation of handle.
Func (Mux *servemux) Handlefunc (pattern string, handler func (Responsewriter, *request)) {
mux. Handle (Pattern, Handlerfunc (handler))
}
2.3 Handler
Handler is based on the access path of request, find the related routing table, get the processing function
Func (Mux *servemux) Handler (R *request) (H Handler, pattern string) {if R.method!= "CONNECT" { If p: = CleanPath (R.url. Path); P!= R.url. Path {_, pattern = Mux.handler (r.host, p) URL: = *r.url url.p Ath = P return redirecthandler (URL. String (), statusmovedpermanently), pattern}} return Mux.handler (R.host, R.URL.P ATH)} func (Mux *servemux) handler (host, path string) (H handler, pattern string) {mux.mu.
Rlock () defer mux.mu.RUnlock ()//Host-specific pattern takes precedence over generic ones
If mux.hosts {h, pattern = mux.match (host + Path)} if H = = Nil { H, pattern = Mux.match (path)} if H = nil {h, pattern = Notfoundhandler () , ""} Return
}
2.4 servehttp
Serverhttp is the gateway to the route.
Func (Mux *servemux) servehttp (w responsewriter, R *request) {
//Below is the process URL path
If R.requesturi = "*" {
if R.prot Oatleast (1, 1) {
w.header (). Set ("Connection", "Close")
}
W.writeheader (statusbadrequest)
return
}
//Find Handler
H, _ : = Mux. Handler (R)
//Specific processing
h.servehttp (W, R)
}
2.5 Defaultservemux
Default route, just a layer of DEFAULTSERVEMUX encapsulation
Func Handle (pattern string, handler handler) {Defaultservemux.handle (pattern, handler)}
func Handlefunc (pattern String, handler func (Responsewriter, *request)) {
Defaultservemux.handlefunc (pattern, handler)
}
3 Server
Portal, creating and listening.
is actually creating a server object
Func listenandserve (addr string, handler handler) error {
server: = &server{addr:addr, handler:handler}
ret Urn server. Listenandserve ()
}
Look at what the server has to offer
Type Server
func (SRV *server) listenandserve () Error
func (SRV *server) listenandservetls (CertFile, keyfile String) Error
func (SRV *server) Serve (l net. Listener) Error
func (SRV *server) setkeepalivesenabled (v bool)
Below we trace the process 3.1 listenandserve
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)})
}
Where listen returns a listener interface.
Func Listen (NET, laddr string) (Listener, error)
type Listener interface {
//Accept waits for and returns the N Ext connection to the listener.
Accept () (Conn, error)
//close closes the listener.
Any blocked Accept operations is unblocked and return errors.
Close () error
//ADDR Returns the listener's network address.
ADDR () Addr
}
3.2 Serve
The real entrance.
Step: Accept–>srv.newconn–>c.serve (CTX)
Func (SRV *server) Serve (l net. Listener) Error {defer l.close () if fn: = Testhookserverserve; fn!= nil {fn (SRV , L)} var tempdelay time. Duration//How long to sleep on accept failure If err: = Srv.setuphttp2_serve (); Err!= nil {return err}//Todo:allow changing base context?
Can ' t imagine concrete//use cases yet. Basectx: = Context. Background () CTX: = Context. Withvalue (Basectx, Servercontextkey, srv) CTX = context. Withvalue (CTX, Localaddrcontextkey, L.addr ()) for {//Call Accept listener RW, e: = l.accept () if E!= nil {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.log F ("Http:accept error:%v; Retrying in%v ", E, Tempdelay) time.
Sleep (Tempdelay) Continue} return E} Tempdelay = 0//Get new link c: = Srv.newconn (rw) c.setstate (C.RWC, statenew)//Before Serve can return//link processing place go c.serve (CTX)}}
4 Conn
4.1 newconn
CREATED a conn
Func (SRV *server) newconn (RWC net. Conn) *conn {
c: = &conn{
server:srv,
RWC: RWC,
}
if debugserverconnections {
C.RWC = Newloggingconn ("Server", C.RWC)
} return
c
}
4.2 Serve
Read the data in the Conn and then process it.
Serve a new connection.
Func (c *conn) serve (CTX context. Context) {
c.remoteaddr = c.rwc.remoteaddr (). String () ...
C.R = &CONNREADER{R:C.RWC}
c.bufr = Newbufioreader (C.R)
C.BUFW = Newbufiowritersize (checkconnerrorwriter {c}, 4<<10)
ctx, Cancelctx: = context. Withcancel (CTX)
defer cancelctx ()
for {
W, err: = C.readrequest (CTX)
...
The real processing place
Serverhandler{c.server}. Servehttp (W, w.req)
w.cancelctx ()
if c.hijacked () {
return
}
w.finishrequest ()
if! W.shouldreuseconnection () {
if W.requestbodylimithit | | w.closedrequestbodyearly () {
c.closewriteandwait ( )
}
return
}
c.setstate (C.RWC, Stateidle)
}
}
4.3 servehttp
The final place. By looking for routes, find the route handler function, and then respond to the request information.
Type Serverhandler struct {
srv *server
}
func (Sh serverhandler) servehttp (rw responsewriter, req *request) {
Handler: = Sh.srv.Handler
//nil uses the default route
if handler = = Nil {
handler = Defaultservemux
}
if Req. RequestUri = "*" && req. method = = "Options" {
handler = globaloptionshandler{}
}
handler. Servehttp (rw, req)
}
5 SummaryRouting section, build a map to store the routing processing Function link processing part, constructs a TCP listener, then accept, constructs the Conn then through Conn, looks for the route, locates the processing function, carries on the processing
Hao Haohua
QQ 29185807 Crescent moon-Dao Chang
December 12, 2016