动手-用Golang实现一个小型Web服务器

在实现Web服务器实现,我们需要了解HTTP 协议

  • HTTP 报文分为 响应报文 与 请求报文
    //报文头
     GET /index.html HTTP/1.1  //说明请求类型 GET POST PUT DELETE .... 页面为index.html
     Host: hackr.jp  // 在主机hackr.jp 上
     User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/2010010  //浏览器请求头
     Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*//*; q=0
     Accept-Language: ja,en-us;q=0.7,en;q=0.3
     Accept-Encoding: gzip, deflate
     DNT: 1
     Connection: keep-alive
     If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT
     If-None-Match: "45bae1-16a-46d776ac"
     Cache-Control: max-age=0
     ``
    

响应报文

HTTP/1.1 304 Not Modified //状态码
Date: Thu, 07 Jun 2012 07:21:36 GMT //响应时间
Server: Apache //服务器
Connection: close // 是否与服务器链接
Etag: "45bae1-16a-46d776ac" //请求资源的Etag

效果

在这里插入图片描述
在这里插入图片描述

实现

  • main.go
package main

import (
	"sync"
)

var wg sync.WaitGroup

func main() {

	go Accpect()
	wg.Add(1)
	wg.Wait()
}
  • WebServer .go
package main

import (
	"fmt"
	"io"
	"net"
	"os"
	"regexp"
	"strings"
)

var (
	address string = "127.0.1:5678"
)

func Accpect() {
	conn, err := net.Listen("tcp", address)
	if err != nil {
		fmt.Print(err)
		return
	}
	defer conn.Close()

	client, err := conn.Accept()
	if err != nil {

		fmt.Print(err)
		return
	}
	buff := make([]byte, 2048)
	client.Read(buff)

	Response(client, buff)
}
func Resolving(header []byte) map[string]string {

	//用户保存解析后的报文信息
	ResponseArray := make(map[string]string, 8)
	for index, v := range strings.Split(string(header), "\n") {

		if len(v) == 1 || v == "" {
			continue
		}

		if index == 0 {
			Compiles := regexp.MustCompile(`([A-Z]{3}) /([A-Za-z0-9 .]*) HTTP/1.1`)
			result := Compiles.FindStringSubmatch(v)

			ResponseArray["Method"] = result[1]
			ResponseArray["page"] = result[2]

		} else {

			splitArray := strings.Split(v, ":")
			if len(splitArray) == 1 {
				continue
			}
			ResponseArray[splitArray[0]] = strings.Replace(splitArray[1], " ", "", -1)
		}

	}

	return ResponseArray
}
func ReadFile(path string) string {
	Html := ""
	buff := make([]byte, 1024)
	File, err := os.Open(path)
	if err != nil {
		return "找不到该路径"
	} else {
		for {
			_, readerr := File.Read(buff)
			if readerr == io.EOF {
				break
			}

			Html += string(buff)

		}
		return Html
	}
}

//对请求进行响应
func Response(conn net.Conn, buff []byte) {
	defer conn.Close()

	ResoArray := make(map[string]string, 8)
	ResoArray = Resolving(buff)
	ResponseHead := "HTTP/1.1 200 OK"
	ResponseHead += "\n"
	ResponseHead += "Date: Thu, 07 Jun 2012 07:21:36 GMT"
	ResponseHead += "\n"
	ResponseHead += "Content-Type: text/html"
	ResponseHead += "\n"
	ResponseHead += "Server:yhWebServer"
	ResponseHead += "\n"
	ResponseHead += "Connection: close"
	ResponseHead += "\n \n\n\n"
	paths := fmt.Sprintf("/home/yh/vpnDemo/web/%s/%s", ResoArray["Host"], ResoArray["page"])
	ResponseHead += ReadFile(paths)
	ResponseHead += "\n"
	//fmt.Print(ResponseHead)
	conn.Write([]byte(ResponseHead))
}


``
// go run main.go WebServer.go 运行

版权声明:本文为qq_45535340原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。