關於HTTP協議,可以參考:
首先直接用標準庫的net/http包
package main
import (
"log"
"net/http"
)
func index(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
}
func main() {
http.HandleFunc("/", index)
log.Println("Now Listening...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Socket實現:
package main
import (
"io/ioutil"
"log"
"net"
"strconv"
"strings"
"time"
)
//簡單的響應結構體
type Response struct {
net.Conn
header map[string]string
code int
status string
}
//newResponse
func NewResponse(conn net.Conn) *Response {
return &Response{
Conn: conn,
header: make(map[string]string),
}
}
//響應消息報頭
func (this *Response) WriteHeader(key, value string) {
this.header[key] = value
}
//響應狀態
func (this *Response) Status(code int, status string) {
this.code = code
this.status = status
}
//響應
func (this *Response) Write(data []byte) {
this.Status(200, "OK")
wheader := []byte("HTTP/1.1 " + strconv.Itoa(this.code) + " " + this.status + "\n")
this.WriteHeader("Content-Type", "text/html")
this.WriteHeader("Date", time.Now().Format(time.RFC1123))
this.WriteHeader("Content-Length", strconv.Itoa(len(data)))
for k, v := range this.header {
wheader = append(wheader, []byte(k+":"+v+"\n")...)
}
wheader = append(wheader, '\n')
log.Println(string(wheader))
log.Println(string(data))
this.Conn.Write(wheader)
this.Conn.Write(data)
}
//讀取文件
func getFileContent(path string) []byte {
data, err := ioutil.ReadFile(path)
CheckErr("read file error:", err)
return data
}
func CheckErr(errInfo string, err error) {
if err != nil {
log.Fatalln(errInfo, err.Error())
}
}
func Handle(conn net.Conn) {
r := ParseRequest(conn)
w := NewResponse(conn)
var data []byte
if r.path[1:] != "" {
if r.path[1:] != "favicon.ico" {
data = getFileContent(r.path)
} else {
data = []byte{}
}
} else {
data = getFileContent("./index.html")
}
w.Write(data)
conn.Close()
}
//簡單請求結構體
type Request struct {
method string
path string
//header map[string]string
}
//解釋請求
func ParseRequest(conn net.Conn) *Request {
rbuf := make([]byte, 1024)
n, err := conn.Read(rbuf)
if err != nil {
log.Println("connection read err:", err)
conn.Close()
}
rbuf = rbuf[:n]
mindex := strings.Index(string(rbuf), "/")
method := strings.Trim(string(rbuf[:mindex]), " ")
path := strings.Trim(getMidStr(string(rbuf), method, "HTTP/"), " ")
return &Request{
method: method,
path: path,
}
}
func getMidStr(str, start, end string) string {
stIndex := strings.Index(str, start)
if stIndex > -1 {
endIndex := strings.Index(str, end)
if endIndex > stIndex {
return str[stIndex+len(start) : endIndex]
}
}
return ""
}
func main() {
ls, err := net.Listen("tcp", ":8080")
CheckErr("listen err:", err)
defer ls.Close()
log.Println("Now Listening...")
for {
conn, err := ls.Accept()
if err != nil {
log.Println("Accept err:", err.Error())
conn.Close()
continue
}
go Handle(conn)
}
}