使用Go搭建一个Web服务器

1,208 阅读3分钟

Web服务器的工作原理可以简单地归纳为:

  1. 客户机通过TCP/IP协议建立到服务器的TCP连接

  2. 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档

  3. 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调 用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端

  4. 客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果

URL的组成

url是(Uniform Resource Locator)"统一资源定位符"的英文缩写,用于描述网络上的资源,基本格式如下:

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 锚

HTTP请求包和响应包

Request包分为3部分

  1. 第一部分叫Request line(请求行)

  2. 第二部分叫Request header(请求头)

  3. 第三部分是body(主体), header和body之间有个空行

    POST http:/test.domain.net/manage/getTask HTTP/1.1   // 此处是请求行, 分别表示:请求方法 请求URI	 HTT协议/协议版本
    Host: test.domain.net  // 服务端的主机名
    Content-Length: 72
    Accept: application/json, text/plain, */*
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.55   // //浏览器信息
    Content-Type: application/json;charset=UTF-8
    Accept-Encoding: gzip, deflate   // //是否支持流压缩
    											// 空行,用于分割请求头和消息体
    {"taskStatus":"1","isTabCv":"1","execType":"SQL","pageSize":30,"page":1}   // 消息体,请求资源参数,
    

Response包

Response包中的第一行叫做状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Sun, 06 Dec 2020 07:35:26 GMT   //发送时间
Content-Type: text/html //服务器发送信息的类型
Connection: keep-alive 	//保持连接状态
Content-Length: 90 	//主体内容长度
						//空行 用来分割消息头和主体
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compati...  //消息体

状态码告诉我们,http服务端是否产生的预期的Response,HTTP协议中,有如下几种状态码

  1. 1XX 提示信息 - 表示请求已被成功接收,继续处理
  2. 2XX 成功 - 表示请求已被成功接收,理解,接受
  3. 3XX 重定向 - 要完成请求必须进行更进一步的处理
  4. 4XX 客户端错误 - 请求有语法错误或请求无法实现
  5. 5XX 服务器端错误 - 服务器未能实现合法的请求

Go搭建一个Web服务器

Go语言里面提供了net/http标准包,可以很方便的搭建起来一个的Web服务。同时使用这个包能很简单地对Web的路 由,静态文件,模版,cookie等数据进行设置和操作。

// 设置访问的路由
	http.HandleFunc("/", func(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"])

		fmt.Fprintf(w, "hello word")   //这个写入到w的是输出到客户端的
	})

	// 设置监听的端口
	err := http.ListenAndServe(":7070", nil)

	if err != nil {
		log.Fatal(err)
	}

使用浏览器访问 localhost:7070