• Golang网络编程-HTTP编程实战篇


              Golang网络编程-HTTP编程实战篇

                                   作者:尹正杰

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

     

     

     

     

    一.HTTP概述

    1>.HTTP概述

      一个Web服务器也被称为HTTP服务器,它通过HTTP (HyperText Transfer Protocol 超文本传输协议)协议与客户端通信。这个客户端通常指的是Web浏览器(其实手机端客户端内部也是浏览器实现的)。
    
      Web服务器的工作原理可以简单地归纳为:
        1>.客户机通过TCP/IP协议建立到服务器的TCP连接
        2>.客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档
        3>.服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端
        4>.客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果

    2>.HTTP协议

      超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议,它详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。
    
      HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候,就成了我们常说的HTTPS。

    3>.HTTP请求报文格式说明

      如上图所示,HTTP 请求报文由请求行、请求头部、空行、请求包体4个部分组成。
    
      请求行
        请求行由方法字段、URL字段 和HTTP 协议版本字段 3个部分组成,他们之间使用空格隔开。常用的 HTTP 请求方法有GET、POST。
          GET:
            当客户端要从服务器中读取某个资源时,使用GET 方法。GET 方法要求服务器将URL 定位的资源放在响应报文的数据部分,回送给客户端,即向服务器请求某个资源。
            使用GET方法时,请求参数和对应的值附加在 URL 后面,利用一个问号(“?”)代表URL 的结尾与请求参数的开始,传递参数长度受限制,因此GET方法不适合用于上传数据。
            通过GET方法来获取网页时,参数会显示在浏览器地址栏上,因此保密性很差。
          POST:
            当客户端给服务器提供信息较多时可以使用POST 方法,POST 方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。
            GET 一般用于获取/查询资源信息,POST 会附带用户数据,一般用于更新资源信息。POST 方法将请求参数封装在HTTP 请求数据中,而且长度没有限制,因为POST携带的数据,在HTTP的请求正文中,以名称/值的形式出现,可以传输大量数据。
      请求头部     请求头部为请求报文添加了一些附加信息,由“名
    /值”对组成,每行一对,名和值之间使用冒号分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:       User-Agent:         请求的浏览器类型       Accept:         客户端可识别的响应内容类型列表,星号("*")用于按范围将类型分组,用"*/*"指示可接受全部类型,用"type/*"指示可接受 type 类型的所有子类型       Accept-Language:         客户端可接受的自然语言       Accept-Encoding:         客户端可接受的编码压缩格式       Accept-Charset:         可接受的应答的字符集       Host:         请求的主机名,允许多个域名同处一个IP 地址,即虚拟主机       connection:         连接方式(close或keepalive)       Cookie:         存储于客户端扩展字段,向同一域名的服务端发送属于该域的cookie
      空行     最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
      请求包体     请求包体不在GET方法中使用,而在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型Content
    -Type和包体长度Content-Length。

    4>.HTTP响应报文说明

      如上图所示,HTTP 响应报文由状态行、响应头部、空行、响应包体4个部分组成。
    
      状态行
        状态行由 HTTP 协议版本字段、状态码和状态码的描述文本3个部分组成,他们之间使用空格隔开。
        状态码:状态码由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示:
          1xx:    
            表示服务器已接收了客户端请求,客户端可继续发送请求
          2xx:
            表示服务器已成功接收到请求并进行处理
          3xx:
            表示服务器要求客户端重定向
          4xx:
            表示客户端的请求有非法内容
          5xx:
            表示服务器未能正常处理客户端的请求而出现意外错误
        常见的状态码举例:
          200:
            表示OK,即客户端请求成功
          400:
            表示Bad Request,即请求报文有语法错误
          401:
            表示Unauthorized,即未授权
          403:
            表示Forbidden,即服务器拒绝服务
          404:
            表示Not Found,即请求的资源不存在
          500:
            表示Internal Server Error,即服务器内部错误
          503:
            表示Server Unavailable,即服务器临时不能处理客户端请求(稍后可能可以)
    
      响应头部
        响应头可能包括:
          Location:
            响应报头域用于重定向接受者到一个新的位置
          Server:
            响应报头域包含了服务器用来处理请求的软件信息及其版本
          Vary:
            指示不可缓存的请求头列表
          Connection:
            连接方式
    
      空行
        最后一个响应头部之后是一个空行,发送回车符和换行符,通知服务器以下不再有响应头部。
    
      响应包体
        服务器返回给客户端的文本信息。

    5>.博主推荐阅读

      http协议版本,工作机制及http服务器应用扫盲篇:
        https://www.cnblogs.com/yinzhengjie/p/11986869.html
    
      HTTP协议详解:
        https://www.cnblogs.com/yinzhengjie/p/12014076.html
    
      前后端分离-Restful最佳实践
        https://www.cnblogs.com/yinzhengjie/p/12037939.html

    二.使用Golang编写一个简单的Web服务器(生产环境建议初学者使用开源的web框架,比如Beego,Gin等)

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func UserResp(resp http.ResponseWriter, req *http.Request) {
        fmt.Printf("请求方法: %s
    ", req.Method)
        fmt.Printf("浏览器发送请求文件路径: %s
    ", req.URL)
        fmt.Printf("请求头: %s
    ", req.Header)
        fmt.Printf("请求包体: %s
    ", req.Body)
        fmt.Printf("客户端网络地址: %s
    ", req.RemoteAddr)
        fmt.Printf("客户端Agent: %s
    ", req.UserAgent())
    
        /**
        给客户端回复数据
        */
        resp.Write([]byte("User response"))
    }
    
    func IndexResp(resp http.ResponseWriter, req *http.Request) {
        resp.Write([]byte("Index response"))
    }
    
    func main() {
        /**
        为不同的请求注册不同的函数
        */
        http.HandleFunc("/user", UserResp)
        http.HandleFunc("/index", IndexResp)
    
        //开启服务器,监听客户端的请求
        http.ListenAndServe("127.0.0.1:8080", nil)
    
    }

    三.使用Golang发起HTTP请求

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func main() {
    
        /**
        该URL是咱们自己刚刚编写简单的Web服务器对应的资源。
        */
        url := "http://127.0.0.1:8080/user"
    
        resp, err := http.Get(url)
        if err != nil {
            fmt.Println("获取数据失败,错误原因: ", err)
            return
        }
        defer resp.Body.Close()
    
        /**
        获取从服务器端读到数据
        */
        fmt.Printf("状态: %s
    ", resp.Status)
        fmt.Printf("状态码: %v
    ", resp.StatusCode)
        fmt.Printf("响应头部: %s
    ", resp.Header)
        fmt.Println("响应包体: ", resp.Body)
    
        /**
        定义切片缓冲区,临时存储读到的数据,并将每次读到的结果拼接到data中
        */
        buf := make([]byte, 4096)
        var data string
    
        for {
            n, _ := resp.Body.Read(buf)
            if n == 0 {
                fmt.Println("数据读取完毕....")
                break
            }
            if err != nil {
                fmt.Println("数据读取失败,错误原因: ", err)
                return
            }
            data += string(buf[:n])
        }
    
        fmt.Printf("从服务端获取到的内容是: [%s]
    ", data)
    }

  • 相关阅读:
    Ubuntu自启动服务脚本
    坑(一)—— Django ORM 连接超时的坑
    logging模块详解
    端口扫描之nmap命令
    端口扫描之masscan扫描
    端口扫描之Scapy模块的使用
    端口扫描之开放端口扫描方式
    Android Studio导入Project、Module的正确方法
    ImportError: No module named 'requests'
    运行python程序
  • 原文地址:https://www.cnblogs.com/yinzhengjie2020/p/12723694.html
Copyright © 2020-2023  润新知