这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战
HTTP协议详解
HTTP 超文本传输协议 (HTTP-Hypertext transfer protocol),是一个属于应用层的 面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于 1990 年提出,经过几年的使用与发展,得到不断地完善和扩展。它是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。 客户端与服务端通信时传输的内容我们称之为报文.
HTTP 就是一个通信规则,这个规则规定了客户端发送给服务器的报文格式,也规定了服务器响应给客户端的报文格式。实际我们要学习的就是这两种报文。客户端发送给服务器的称为”请求报文“,服务器发响应给客户端的称为”响应报文“。
HTTP协议是Web工作的核心,所以要了解清楚Web的工作方式就需要详细的了解清楚HTTP是怎么样工作的。
HTTP是一种让Web服务器与浏览器(客户端) 通过Internet发送与接收数据的协议,它建立在TCP协议之上,一般采用TCP的80端口。它是一个请求、响应协议--客户端发出一个请求,服务器响应这个请求。在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回调连接。客户端与服务器端都可以提前中断一个连接。例如,当浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。
HTTP协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系的,对HTTP服务器来说,它并不知道这两个请求是否来自同一个客户端。为了解决这个问题, Web程序引入了Cookie机制来维护连接的可持续状态。
HTTP协议是建立在TCP协议之上的,因此TCP攻击一样会影响HTTP的通讯,例如比较常见的一些攻击:SYN Flood是当前最流行的DoS(拒绝服务攻击)与DdoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。
HTTP 协议的会话方式
浏览器与 WEB 服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一 个页面的访问,浏览器与 WEB 服务器都要建立一次单独的连接。
浏览器到 WEB 服务器之间的所有通讯都是完全独立分开的请求和响应对。
Go语言里面提供了一个完善的net/http包,通过http包可以很方便的搭建起来一个可以运行的Web服务。同时使用这个包能很简单地对Web的路由,静态文件,模版,cookie等数据进行设置和操作。
http包建立Web服务器
package main
import (
"fmt"
"net/http"
"strings"
"log"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析参数,默认是不会解析的
fmt.Println(r.Form) //这些信息是输出到服务器端的打印信息
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello afei!") //这个写入到w的是输出到客户端的
}
func main() {
http.HandleFunc("/", sayhelloName) //设置访问的路由
err := http.ListenAndServe(":9090", nil) //设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
上面这个代码,我们build之后,然后执行web.exe,这个时候其实已经在9090端口监听http链接请求了。
在浏览器输入http://localhost:9090
可以看到浏览器页面输出了Hello afei!
可以换一个地址试试:http://localhost:9090/?url_long=111&url_long=222
我们看到上面的代码,要编写一个Web服务器很简单,只要调用http包的两个函数就可以了
package main
import (
"fmt"
"log"
"net/http"
"strings"
)
func quickWeb(w http.ResponseWriter,r *http.Request) {
fmt.Fprintf(w,"helo afei.")
}
func main() {
http.HandleFunc("/quickWeb", quickWeb) //设置访问的路由
err := http.ListenAndServe(":8080", nil) //设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}