设为首页 加入收藏

TOP

golang http server分析(一)(一)
2017-09-30 13:35:20 】 浏览:882
Tags:golang http server分析

golang中使用的http协议版本是RFC2616

对于一个http服务来讲,需要兼容新旧版本的http协议,http1.0/2.0,以及https的支持,http的通信是建立在tcp连接基础上的通信。

现在协议有了,连接通信也有了,还剩一个问题就是如何处理client request请求,这个问题可以分为路由和具体逻辑实现,下面看看在golang中是如何解决这些问题的。

 

路由部分 

在golang中有个Handler的概念,一个URL对应一个Handler,在Handler中处理request的具体逻辑,对应关系保存在一个map结构中

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry //key是URL匹配字符串,muxEntry是对应的处理handler hosts bool // 路由匹配时,是否包含host }

Handler分为一般类型Handler和特殊类型Handler,特殊类型Handler是指包含特定功能处理的Handler,

比如redirectHandler用来处理302跳转、NotFoundHandler用来处理404请求等。

Handler定义如下:

// Handler类型定义
type Handler interface {
    ServeHTTP(ResponseWriter, *Request) } //一般Handler是一函数体,实现了Handler接口,通过该函数可以将一个自定义函数转换为Handler type HandlerFunc func(ResponseWriter, *Request) // 绑定对象就是自定义函数本身,通过在ServerHTTP中调用函数本身,实现了钩子功能。 // 也就是说,当程序调用Handler.ServerHTTP()方法的时候,实际上是调用的跟Handler绑定的自定义函数 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { // 调用绑定对象函数  f(w, r) }

 

明确了Handler的定义,接下来就要看看如何注册Handler了,Handler的注册是通过HandleFunc()函数实现的,在HandleFunc中调用ServerMux的HandleFunc()

方法将一个自定义的方法转换为一个一般Handler,最后再调用Server.Mux的handle()方法,完成URL与Handler的绑定,下面详细看看handle()的实现,

func (mux *ServeMux) Handle(pattern string, handler Handler) {
    // 加一个写锁
 mux.mu.Lock() defer mux.mu.Unlock() // url匹配字符串不能为空 if pattern == "" { panic("http: invalid pattern " + pattern) } // handler不能为空 if handler == nil { panic("http: nil handler") } // 对应关系没有被注册过 if mux.m[pattern].explicit { panic("http: multiple registrations for " + pattern) } // 添加到map mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern} // 判断是否以hosts开头的url if pattern[0] != '/' { mux.hosts = true } // 如果URL以字符/结尾,则多注册注册一个redirectHandler,访问/tree时重定向到/tree/ n := len(pattern) if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit { path := pattern if pattern[0] != '/' { path = pattern[strings.Index(pattern, "/"):] } url := &url.URL{Path: path} mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern} } }

 

redirectHandle定义:

// redirectHandler是一个结构体,实现了Handler接口
type redirectHandler struct {
    url  string code int } func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) { // 重定向,设置location,status  Redirect(w, r, rh.url, rh.code) }

 

通信部分

http请求过程实质上是一个tcp连接通信,具体通过socket接口编码实现,socket部分另起文章详细说明,这里只做简单介绍,socket操作流程如下:

在golang中的使用,通过listenAndServer()函数一步完成

func (srv *Server) ListenAndServe() error {
    addr := srv.Addr if addr == "" { addr = ":http" } // 创建socket文件描述符,绑定ip:port,改变socket状态为监听状态 ln, err := net.Listen("tcp", addr) if err != nil { return err } // 启动服务,处理连接请求,tcpKeepAliveListener是一个长连接 return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) }

 在svr.Server()函数中会循环Accept() tcp 连接请求,每当读取到一个tcp conn就启动一个goroutine去处理连接信息,

 对于http服务来讲,在goroutine中完成了http request的处理流程如下

 

readRequest():从tcp conn中读取一个http request,完成了http请求的heand以及body的解析依据http协议对请求信息的校验,详细过程如下

1. 设置tcp conn读取数据超时时间,设置请求头数据大小限制,过滤http1.0 post请求后多添加的空格

2. 读取请求信息并格式化

3. 校验请求头信息是否合法

4. 封装成一个response返回,下面详细介绍

 

获取到请求信息,接下来就该调用URL对应的具体逻辑了,通过Handler.ServerHTTP()完成了对Handler的调用,主要操作如下:

1. 根据请求信息host,path在serv

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Golang 笔记 1 基础、基本数据类型 下一篇golang socket 实现分析(一)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目