https://blog.csdn.net/zhizhengguan/article/details/108026066
package main
import (
"fmt"
"net"
)
func accept_request_thread(conn net.Conn) {
defer conn.Close()
for {
// 创建一个新切片, 用作保存数据的缓冲区
buf := make([]byte, 1024)
n, err := conn.Read(buf) // 从conn中读取客户端发送的数据内容
if err != nil {
fmt.Printf("客户端退出 err=%v\n", err)
return
}
fmt.Printf(" 接受消息 %s\n", string(buf[:n]))
}
}
func main() {
listen, err := net.Listen("tcp", ":8888") // 创建用于监听的 socket
if err != nil {
fmt.Println("listen err=", err)
return
}
fmt.Println("监听套接字,创建成功, 服务器开始监听。。。")
defer listen.Close() // 服务器结束前关闭 listener
// 循环等待客户端来链接
for {
fmt.Println("阻塞等待客户端来链接...")
conn, err := listen.Accept() // 创建用户数据通信的socket
if err != nil {
fmt.Println("Accept() err=", err)
} else {
fmt.Println("通信套接字,创建成功。。。")
}
// 这里准备起一个协程,为客户端服务
go accept_request_thread(conn)
}
}
http://192.168.0.20:8888/api/camera/get_ptz?camera_id=1324566666789876543
我们接下来的任务就是 解析这些字符串,从中获取 当前是什么方法,什么请求,参数是什么?
先定义一个小目标,获取当前是什么方法。
package main
import (
"encoding/json"
"fmt"
"log"
"net"
"strings"
)
func unimplemented(conn net.Conn){
var buf string
buf = "HTTP/1.0 501 Method Not Implemented\r\n"
_, _ = conn.Write([]byte(buf))
buf = "Server: httpd/0.1.0\r\n"
_, _ = conn.Write([]byte(buf))
buf = "Content-Type: text/html\r\n"
_, _ = conn.Write([]byte(buf))
buf = "\r\n"
_, _ = conn.Write([]byte(buf))
buf = "Method Not Implemented\r\n"
_, _ = conn.Write([]byte(buf))
buf = "\r\n"
_, _ = conn.Write([]byte(buf))
buf = "HTTP request method not supported.\r\n"
_, _ = conn.Write([]byte(buf))
buf = "\r\n"
_, _ = conn.Write([]byte(buf))
}
func accept_request_thread(conn net.Conn) {
defer conn.Close()
var i int
buf := make([]byte, 1024)
n, err := conn.Read(buf) // 从conn中读取客户端发送的数据内容
if err != nil {
fmt.Printf("客户端退出 err=%v\n", err)
return
}
// 获取方法
i = 0
var method_bt strings.Builder
for(i < n && buf[i] != ' '){
method_bt.WriteByte(buf[i])
i++;
}
method := method_bt.String()
if(method != "GET"){
unimplemented(conn)
return
}
for(i < n && buf[i] == ' '){
i++
}
//api/camera/get_ptz?camera_id=1324566666789876543
var url_bt strings.Builder
for(i < n && buf[i] != ' '){
url_bt.WriteByte(buf[i])
i++;
}
url := url_bt.String()
if(method == "GET"){
//url ---> /api/camera/get_ptz?camera_id=1324566666789876543
// 跳到第一个?
var path, query_string string
j := strings.IndexAny(url, "?")
if(j != -1){
path = url[:j]
if(j + 1 < len(url)){
query_string = url[j+1:]
}
}else{
path = url
}
fmt.Print(path + "请求已经创建\t")
resp := execute(path, query_string)// =1324566666789876543
fmt.Println("返回", string(resp))
header(conn, "application/json", len(resp));
_ , err := conn.Write(resp)
if(err != nil){
fmt.Println(err)
}
}
}
//回应客户端必须先设置好head头,浏览器才能解析
func header(conn net.Conn, content_type string , length int ) {
var buf string
buf = "HTTP/1.0 200 OK\r\n"
_, _ = conn.Write([]byte(buf))
buf = "Server: httpd/0.1.0\r\n"
_, _ = conn.Write([]byte(buf))
buf = "Content-Type: " + content_type + "\r\n"
_, _ = conn.Write([]byte(buf))
_, _ = fmt.Sscanf(buf, "Content-Length: %d\r\n", length)
buf = "Content-Type: " + content_type + "\r\n"
_, _ = conn.Write([]byte(buf))
buf = "\r\n"
_, _ = conn.Write([]byte(buf))
}
func execute(path string, query_string string) ([]byte) {
query_params := make(map[string]string)
parse_query_params(query_string, query_params)
if("/api/camera/get_ptz" == path){
/*
* do something
*/
camera_id := query_params["camera_id"]
resp := make(map[string]interface{
})
resp["camera_id"] = camera_id
resp["code"] = 200
resp["msg"] = "ok"
rs, err := json.Marshal(resp)
if err != nil{
log.Fatalln(err)
}
return rs
}else if("get_abc" == path){
/*
* do something
*/
return []byte("abcdcvfdswa")
}
return []byte("do't match")
}
/*map作为函数入参是作为指针进行传递的
函数里面对map进行修改时,会同时修改源map的值,但是将map修改为nil时,则达不到预期效果。*/
// camera_id=1324566666789876543&tt=%E5%88%9B%E5%BB%BA%E6%88%90%E5%8A%9F
func parse_query_params(query_string string, query_params map[string]string) {
kvs := strings.Split(query_string, "&")
if(len(kvs) == 0){
return
}
for _, kv := range kvs {
kv := strings.Split(kv, "=")
if(len(kv) != 2){
continue
}
query_params[kv[0]] = kv[1]
}
}
func main() {
listen, err := net.Listen("tcp", ":8888") // 创建用于监听的 socket
if err != nil {
fmt.Println("listen err=", err)
return
}
fmt.Println("监听套接字,创建成功, 服务器开始监听。。。")
defer listen.Close() // 服务器结束前关闭 listener
// 循环等待客户端链接
for {
fmt.Println("阻塞等待客户端链接...")
conn, err := listen.Accept() // 创建用户数据通信的socket
if err != nil {
panic("Accept() err= " + err.Error())
}
// 这里准备起一个协程,为客户端服务
go accept_request_thread(conn)
}
}