]> 127.0.0.1 Git - part/.git/commitdiff
websocket和简易web服务 v0.3.9
authorqydysky <qydysky@foxmail.com>
Tue, 2 Feb 2021 12:33:49 +0000 (20:33 +0800)
committerqydysky <qydysky@foxmail.com>
Tue, 2 Feb 2021 12:33:49 +0000 (20:33 +0800)
README.md
go.mod
go.sum
web/Web.go [new file with mode: 0644]
web/Web_test.go [new file with mode: 0644]
web/index.html [new file with mode: 0644]
websocket/Server.go [new file with mode: 0644]
websocket/Server_test.go [new file with mode: 0644]
websocket/index.html [new file with mode: 0644]

index 730a0229128bf214f072dd4880611abde411eb6e..1d899bcbe254be264722d8b01ceb14248a860d39 100644 (file)
--- a/README.md
+++ b/README.md
@@ -11,6 +11,8 @@
 - [github.com/klauspost/compress](https://github.com/klauspost/compress) under [BSD 3-Clause](https://raw.githubusercontent.com/klauspost/compress/master/LICENSE)\r
 - [github.com/andybalholm/brotli](https:github.com/andybalholm/brotli) under [MIT](https://raw.githubusercontent.com/andybalholm/brotli/master/LICENSE)\r
 - [github.com/klauspost/pgzip](https://github.com/klauspost/pgzip) under [MIT](https://raw.githubusercontent.com/klauspost/pgzip/master/LICENSE)\r
+- [github.com/skratchdot/open-golang/open](https://github.com/skratchdot/open-golang) under [MIT](https://raw.githubusercontent.com/skratchdot/open-golang/master/LICENSE)\r
+- [github.com/gorilla/websocket](https://github.com/gorilla/websocket) under [BSD 2-Clause](https://raw.githubusercontent.com/gorilla/websocket/master/LICENSE)\r
 ---\r
 \r
 #### 介绍\r
diff --git a/go.mod b/go.mod
index 61032da396e3d02c9e97312cfe1a187d5985c829..6a79f3ff7b89363072ce20a98c10ca1223b99d26 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,7 @@ require (
        github.com/klauspost/pgzip v1.2.5
        github.com/miekg/dns v1.1.35
        github.com/shirou/gopsutil v3.20.12+incompatible
+       github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
        github.com/thedevsaddam/gojsonq v2.3.0+incompatible
        github.com/thedevsaddam/gojsonq/v2 v2.5.2
        golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
diff --git a/go.sum b/go.sum
index 011911d25adf60f45ca1d5c5776b8d60b5e74cf0..f67c4b20145f15449e84494e2aceb22ed4404e46 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -24,6 +24,8 @@ github.com/shirou/gopsutil v2.20.7+incompatible h1:Ymv4OD12d6zm+2yONe39VSmp2XooJ
 github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shirou/gopsutil v3.20.12+incompatible h1:6VEGkOXP/eP4o2Ilk8cSsX0PhOEfX6leqAnD+urrp9M=
 github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
+github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
 github.com/thedevsaddam/gojsonq v1.9.1 h1:zQulEP43nwmq5EKrNWyIgJVbqDeMdC1qzXM/f5O15a0=
 github.com/thedevsaddam/gojsonq v2.3.0+incompatible h1:i2lFTvGY4LvoZ2VUzedsFlRiyaWcJm3Uh6cQ9+HyQA8=
 github.com/thedevsaddam/gojsonq v2.3.0+incompatible/go.mod h1:RBcQaITThgJAAYKH7FNp2onYodRz8URfsuEGpAch0NA=
diff --git a/web/Web.go b/web/Web.go
new file mode 100644 (file)
index 0000000..5accba5
--- /dev/null
@@ -0,0 +1,53 @@
+package part
+
+import (
+    "net/http"
+       "time"
+       "strconv"
+       "context"
+       p "github.com/qydysky/part"
+)
+
+type Web struct {
+       Server *http.Server
+       mux *http.ServeMux
+}
+
+func New(conf *http.Server) (o *Web) {
+
+       o = new(Web)
+
+       o.Server = conf
+       
+       if o.Server.Addr == `` {o.Server.Addr = "127.0.0.1:"+strconv.Itoa(p.Sys().GetFreePort())}
+       if o.Server.WriteTimeout == 0 {o.Server.WriteTimeout =  time.Second * time.Duration(10)}
+       if o.Server.Handler == nil {
+               o.mux = http.NewServeMux()
+               o.Server.Handler = o.mux
+       }
+
+       go o.Server.ListenAndServe()
+
+       return
+}
+
+func (t *Web) Handle(path_func map[string]func(http.ResponseWriter,*http.Request)) {
+       for k,v := range path_func {
+               t.mux.HandleFunc(k,v)
+       }
+}
+
+func Easy_boot() (*Web) {
+       s := New(&http.Server{})
+       s.Handle(map[string]func(http.ResponseWriter,*http.Request){
+               `/`:func(w http.ResponseWriter,r *http.Request){
+                       var path string = r.URL.Path[1:]
+                       if path == `` {path = `index.html`}
+                       http.ServeFile(w, r, path)
+               },
+               `/exit`:func(w http.ResponseWriter,r *http.Request){
+                       s.Server.Shutdown(context.Background())
+               },
+       })
+       return s
+}
diff --git a/web/Web_test.go b/web/Web_test.go
new file mode 100644 (file)
index 0000000..ec6f209
--- /dev/null
@@ -0,0 +1,12 @@
+package part
+
+import (
+       "testing"
+       "time"
+)
+
+func Test_Server(t *testing.T) {
+       s := Easy_boot()
+       t.Log(`http://`+s.Server.Addr)
+       time.Sleep(time.Second*time.Duration(100))
+}
\ No newline at end of file
diff --git a/web/index.html b/web/index.html
new file mode 100644 (file)
index 0000000..31200c9
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="zh-cmn-Hans">
+  <head>
+    <meta charset="utf-8" />
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+  </head>
+  <body>
+    <h3>ok</h3>
+  </body>
+</html>
diff --git a/websocket/Server.go b/websocket/Server.go
new file mode 100644 (file)
index 0000000..e02374e
--- /dev/null
@@ -0,0 +1,126 @@
+package part
+
+import (
+       "net"
+       "net/http"
+    "time"
+       "github.com/gorilla/websocket"
+       idpool "github.com/qydysky/part/idpool"
+       mq "github.com/qydysky/part/msgq"
+)
+
+type Server struct {
+       ws_mq *mq.Msgq
+       userpool *idpool.Idpool
+}
+
+type Uinterface struct {
+       Id uintptr
+       Data []byte
+}
+
+func New_server() (*Server) {
+       return &Server{
+               ws_mq: mq.New(200),//收发通道
+               userpool: idpool.New(),//浏览器标签页池
+       }
+}
+
+func (t *Server) WS(w http.ResponseWriter, r *http.Request) {
+       upgrader := websocket.Upgrader{}
+
+       ws, err := upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               t.ws_mq.Push_tag(`error`,err)
+               return
+       }
+       defer ws.Close()
+
+       //从池中获取本会话id
+       User := t.userpool.Get()
+       defer t.userpool.Put(User)
+
+
+       //发送
+       t.ws_mq.Pull_tag(map[string]func(interface{})(bool){
+               `send`:func(data interface{})(bool){
+                       if u,ok := data.(Uinterface);ok && u.Id == 0 || u.Id == User.Id{
+                               if err := ws.WriteMessage(websocket.TextMessage,u.Data);err != nil {
+                                       t.ws_mq.Push_tag(`error`,err)
+                                       return true
+                               }
+                       }
+                       return false
+               },
+               `close`:func(data interface{})(bool){
+                       if u,ok := data.(Uinterface);ok && u.Id == 0 || u.Id == User.Id{
+                               return true
+                       }
+                       return false
+               },
+       })
+
+       //接收
+       for {
+               ws.SetReadDeadline(time.Now().Add(time.Second*time.Duration(300)))
+               if _, message, err := ws.ReadMessage();err != nil {
+                       if websocket.IsCloseError(err,websocket.CloseGoingAway) {
+                       } else if err,ok := err.(net.Error);ok && err.Timeout() {
+                               //Timeout , js will reload html
+                       } else {
+                               t.ws_mq.Push_tag(`error`,err)
+                       }
+                       t.ws_mq.Push_tag(`close`,Uinterface{
+                               Id:User.Id,
+                       })
+                       break
+               } else {
+                       t.ws_mq.Push_tag(`recv`,Uinterface{
+                               Id:User.Id,
+                               Data:message,
+                       })
+               }
+       }
+}
+
+//how to use
+// ws_mq.Pull_tag(map[string]func(interface{})(bool){
+//     `recv`:func(data interface{})(bool){
+//             if tmp,ok := data.(Uinterface);ok {
+//                     log.Println(tmp.Id,string(tmp.Data))
+
+//                     if string(tmp.Data) == `close` {
+//                             ws_mq.Push_tag(`close`,Uinterface{//close
+//                                     Id:0,//close all connect
+//                             })
+//                             //or 
+//                             // ws_mq.Push_tag(`close`,Uinterface{//close
+//                             //      Id:tmp.Id,//close this connect
+//                             // })
+//                             return false
+//                     }
+
+//                     ws_mq.Push_tag(`send`,Uinterface{//just reply
+//                             Id:tmp.Id,
+//                             Data:tmp.Data,
+//                     })
+//                     //or
+//                     ws_mq.Push_tag(`send`,Uinterface{//just reply
+//                             Id:0,//send to all
+//                             Data:tmp.Data,
+//                     })
+//             }
+//             return false
+//     },
+//     `error`:func(data interface{})(bool){
+//             log.Println(data)
+//             return false
+//     },
+// })
+func (t *Server) Interface() (*mq.Msgq) {
+       return t.ws_mq
+}
+
+func (t *Server) Len() uint {
+       return t.userpool.Len()
+}
\ No newline at end of file
diff --git a/websocket/Server_test.go b/websocket/Server_test.go
new file mode 100644 (file)
index 0000000..fcf1743
--- /dev/null
@@ -0,0 +1,37 @@
+package part
+
+import (
+       "testing"
+       "net/http"
+       "time"
+       "github.com/skratchdot/open-golang/open"
+       web "github.com/qydysky/part/web"
+)
+
+func Test_Server(t *testing.T) {
+       s := New_server()
+       {
+               ws_mq := s.Interface()
+               ws_mq.Pull_tag(map[string]func(interface{})(bool){
+                       `recv`:func(data interface{})(bool){
+                               if tmp,ok := data.(Uinterface);ok {
+                                       t.Log(tmp.Id,string(tmp.Data))
+                                       ws_mq.Push_tag(`send`,Uinterface{//just reply
+                                               Id:tmp.Id,
+                                               Data:tmp.Data,
+                                       })
+                               }
+                               return false
+                       },
+               })
+       }
+
+       w := web.Easy_boot()
+       open.Run("http://"+w.Server.Addr)
+       w.Handle(map[string]func(http.ResponseWriter,*http.Request){
+               `/ws`:func(w http.ResponseWriter,r *http.Request){
+                       s.WS(w,r)
+               },
+       })
+       time.Sleep(time.Second*time.Duration(100))
+}
\ No newline at end of file
diff --git a/websocket/index.html b/websocket/index.html
new file mode 100644 (file)
index 0000000..5a42ca7
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="zh-cmn-Hans">
+  <head>
+    <meta charset="utf-8" />
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1, maximum-scale=1"
+    />
+  </head>
+  <body>
+    <h3>websocket</h3>
+    <p id="ws"></p>
+    <script>
+      if (window["WebSocket"]) {
+        conn = new WebSocket("ws://" + document.location.host + "/ws");
+        conn.onclose = function () {
+          document.getElementById("ws").innerHTML += `close!`
+        };
+        conn.onmessage = function (evt) {
+            document.getElementById("ws").innerHTML += evt.data+`<br>`
+        };
+
+        setInterval(()=>{
+            conn.send(`send`)
+        },3000)
+      }
+    </script>
+  </body>
+</html>