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

吃我一个平底锅 2024-07-27 08:33:01 阅读 53

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请求包格式

<code>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]))code>

}

在这里插入图片描述

格式:

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。

响应报文

测试代码

<code>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"code>

//先发请求包,服务器回响应包

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]))code>

}

http响应格式

在这里插入图片描述

HTTP 响应报文由状态行、响应头部、空行、响应包体4个部分组成,如下图所示:

在这里插入图片描述

状态行

状态行由 HTTP 协议版本字段、状态码和状态码的描述文本3个部分组成,他们之间使用空格隔开。

状态码:

状态码由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示:

在这里插入图片描述

常见的有:

在这里插入图片描述

响应头部

请求头部类似,为响应报文添加了一些附加信息,响应头可能包括:

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。