Go语言---HTTP编程基础(Web 工作方式、HTTP 协议、请求/响应报文)

HTTP 编程

概述

Web 工作方式

对于普通的上网过程,浏览器本身是一个客户端,当我们输入URL的时候,首先浏览器会去请求 DNS 服务器,通过DNS获取相应的域名对应的IP,然后通过IP 地址找到IP 对应的服务器后,要求建立 TCP 连接,等浏览器发送完 HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTPResponse(响应)包:客户端收到来自服务器的响应后开始渲染这个Response 包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接。
在这里插入图片描述
一个 Web 服务器也被称为HTTP 服务器,它通过 HTTP 协议与客户端通信。这个客户端通常指的是 Web浏览器(其实手机端客户端内部也是浏览器实现的)。

Web 服务器的工作原理可以简单地归纳为:
  • 客户机通过 TCP/IP 协议建立到服务器的 TCP 连接
  • 客户端向服务器发送HTTP 协议请求包,请求服务器里的资源文档
  • 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端
  • 客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果。

HTTP 协议

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

地址URL

URL 全称为 Unique Resource Location,用来表示网络资源,可以理解为网络文件路径。
格式如下:
http://host[":"port][abs_path]
http://192.168.31.1/html/index
URL的长度有限制,不同的服务器的限制值不太相同,但是不能无限长。

http请求包格式

package main

import (
	"fmt"
	"net"
)

func main() {
	listener, err := net.Listen("tcp", ":8000")
	if err != nil {
		fmt.Println("net.Listen.err=", err)
		return
	}

	conn, err1 := listener.Accept()
	if err1 != nil {
		fmt.Println("listener.Accept.err1=", err1)
		return
	}
	defer listener.Close()

	//接受客户端的数据
	buf := make([]byte, 1024*4)
	n, err2 := conn.Read(buf)
	if n == 0 {
		fmt.Println("conn.Read.err2=", err2)
		return
	}

	fmt.Printf("#%v#", string(buf[:n]))
}

在这里插入图片描述

格式:

HTTP 请求报文由请求行、请求头部、空行、请求包体4个部分组成,如下图所示:
在这里插入图片描述

请求行

请求行由方法字段、URL字段 和HTTP协议版本字段 3个部分组成,他们之间使用空格隔开。常用的HTTP 请求方法有GET、POST。

GET:
  • 当客户端要从服务器中读取某个资源时,使用 GET 方法。GET 方法要求服务器将 URL定位的资源放在响应报文的数据部分,回送给客户端,即向服务器请求某个资源。
  • 使用 GET 方法时,请求参数和对应的值附加在 URL 后面,利用一个问号(“?)代表 URI的结尾与请求参数的开始,传递参数长度受限制,因此 GET 方法不适合用于上传数据。
  • 通过 GET方法来获取网页时,参数会显示在浏览器地址栏上,因此保密性很差。
  • 注意:报文GET 后面为我们要的资源
POST:
  • 当客户端给服务器提供信息较多时可以使用POST 方法,POST方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。
  • GET 一般用于获取/查询资源信息,POST 会附带用户数据,一般用于更新资源信息。POST 方法将请求参数封装在HTTP 请求数据中,而且长度没有限制,因为POST携带的数据,在HTTP的请求正文中,以名称/值的形式出现,可以传输大量数据。

请求头

  • 请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之问使用冒号分隔。
  • 请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
    在这里插入图片描述

空行

最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

请求包体

请求包体不在 GET 方法中使用,而是 POST 方法中使用。
POST方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型Content-Type 和包体长度 Content-Length。

响应报文

测试代码

package main

import (
	"fmt"
	"net"
)

func main() {
	//主动连接服务器
	conn, err := net.Dial("tcp", ":8000")
	if err != nil {
		fmt.Println("net.Dial.err=", err)
		return
	}
	defer conn.Close()
	requestBuf := "GET /go HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nAccept-Encoding: gzip, deflate, \r\nAccept-Language: zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7\r\n\r\n"

	//先发请求包,服务器回响应包
	conn.Write([]byte(requestBuf))

	buf := make([]byte, 1024*4)
	n, err1 := conn.Read(buf)
	if err1 != nil {
		fmt.Println("conn.Read.err1=", err1)
		return
	}

	//打印响应报文
	fmt.Printf("#%v#", string(buf[:n]))
}

http响应格式

在这里插入图片描述
HTTP 响应报文由状态行、响应头部、空行、响应包体4个部分组成,如下图所示:
在这里插入图片描述

状态行

状态行由 HTTP 协议版本字段、状态码和状态码的描述文本3个部分组成,他们之间使用空格隔开。
状态码:
状态码由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示:
在这里插入图片描述
常见的有:
在这里插入图片描述

响应头部

与请求头部类似,为响应报文添加了一些附加信息,响应头可能包括:
在这里插入图片描述

  • 35
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值