欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

阅读:《Golang web 应用开发》

程序员文章站 2022-03-15 15:15:49
...

阅读:《Golang web 应用开发》

一. Web工作方式

上网过程

对于普通的上网过程,系统其实是这样做的:浏览器本身是一个客户端,当你输入URL的时候,首先浏览器会去请求DNS服务器,通过DNS获取相应的域名对应的IP,然后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内容随后断开与该服务器之间的TCP连接。

URL和DNS解析

URL解析格式:

scheme://host[:port#]/path/…/[?query-string][#anchor]
scheme 指定底层使用的协议(例如:http, https, ftp)
host HTTP服务器的IP地址或者域名
port# HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
path 访问资源的路径
query-string 发送给http服务器的数据
anchor 锚

DNS解析过程
阅读:《Golang web 应用开发》
通过上面的步骤,我们最后获取的是IP地址,也就是浏览器最后发起请求的时候是基于IP来和服务器做信息交互的。

HTTP协议

  • 在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务
  • HTTP协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系的,对HTTP服务器来说,它并不知道这两个请求是否来自同一个客户端。为了解决这个问题, Web程序引入了Cookie机制来维护连接的可持续状态。

HTTP请求包(浏览器信息)

Request

Request包分为3部分,第一部分叫Request line(请求行), 第二部分叫Request header(请求头),第三部分是body(主体)。header和body之间有个空行,请求包的例子所示:

GET /domains/example/ HTTP/1.1 //请求行: 请求方法 请求URI HTTP协议/协议版本
Host:www.iana.org //服务端的主机名
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4 //浏览器信息
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 //客户端能接收的MIME
Accept-Encoding:gzip,deflate,sdch //是否支持流压缩
Accept-Charset:UTF-8,*;q=0.5 //客户端字符编码集
//空行,用于分割请求头和消息体
//消息体,请求资源参数,例如POST传递的参数

HTTP协议定义了很多与服务器交互的请求方法,最基本的有4种,分别是GET,POST,PUT,DELETE。一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,增,改,删4个操作。我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

HTTP响应包

Respons

HTTP/1.1 200 OK //状态行
Server: nginx/1.0.8 //服务器使用的WEB软件名及版本
Date:Date: Tue, 30 Oct 2012 04:14:25 GMT //发送时间
Content-Type: text/html //服务器发送信息的类型
Transfer-Encoding: chunked //表示发送HTTP包是分段发的
Connection: keep-alive //保持连接状态
Content-Length: 90 //主体内容长度
//空行 用来分割消息头和主体
!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”… //消息体

二. Go搭建一个Web服务器

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 astaxie!") //这个写入到w的是输出到客户端的
}

func main() {
	http.HandleFunc("/", sayhelloName) //设置访问的路由
	err := http.ListenAndServe(":9090", nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

执行结果

阅读:《Golang web 应用开发》
阅读:《Golang web 应用开发》

三. Go创建Web服务器的几种方式

http.HandleFunc函数

使用HandleFunc函数是http封装好的一个函数,可以直接使用,第一个参数是web请求路径,第二个参数是的func(writer http.ResponseWriter, request *http.Request)函数。
再使用http.ListenAndServe(":9090",nil)语句,监听9090端口,运行程序后。
使用http://localhost:9090,便会输出Hello astaxie!
其中http.ResponseWriter代表对客户端的响应体,而http.Request代表客户端发送服务器的请求数据。
http.Handle函数
跟HandleFunc一样,Handle也是http封装好的函数,第一个参数跟HandleFunc一样,而第二个参数则是必须是实现了http.Handler接口的类型,http.Handler在http包的定义如下:

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

http.ServeMux
无论是使用http.Handle还是http.HandleFunc函数,其实底层代码都是使用http.DefaultServeMux,DefaultServeMux的定义如下代码所示:

var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux
type Controller struct {}
func (c Controller)ServeHTTP(writer http.ResponseWriter, request *http.Request){
    writer.Write([]byte("hello,1"));
}

func hello(writer http.ResponseWriter, request *http.Request) {
    writer.Write([]byte("hello,2"));
}

func main(){
    mux := &http.ServeMux{}
    mux.HandleFunc("/hello1",hello)
    mux.Handle("/hello2",http.HandlerFunc(hello))
    mux.Handle("/hello3",&Controller{})

    log.Fatal(http.ListenAndServe(":8080",mux))
}

http.Server
http.Server是http包中对web更加底层的支持,我们前面使用的方法,都是对http.Server的封装而已,如果直接使用http.Server,则可以自定义更多的参数,如果连接超时等参数,因此我们下面直接使用http.Server开发Web服务。

相关标签: Go