update ws
This commit is contained in:
parent
4412bfc727
commit
ea04fd82c8
160
http.go
160
http.go
@ -2,6 +2,7 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -275,14 +276,14 @@ func (hc *Http) Connect(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|||||||
// ws.onPing = opt.Func("onPing")
|
// ws.onPing = opt.Func("onPing")
|
||||||
// ws.onPong = opt.Func("onPong")
|
// ws.onPong = opt.Func("onPong")
|
||||||
ws.onMessage = opt.Func("onMessage")
|
ws.onMessage = opt.Func("onMessage")
|
||||||
ws.onJSONMessage = opt.Func("onJSONMessage")
|
|
||||||
ws.pingInterval = opt.Int64("pingInterval")
|
ws.pingInterval = opt.Int64("pingInterval")
|
||||||
ws.reconnectInterval = opt.Int64("reconnectInterval")
|
ws.reconnectInterval = opt.Int64("reconnectInterval")
|
||||||
if ws.reconnectInterval == 0 && (ws.onMessage != nil || ws.onJSONMessage != nil) {
|
if ws.reconnectInterval == 0 && ws.onMessage != nil {
|
||||||
ws.reconnectInterval = 1000
|
ws.reconnectInterval = 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fmt.Println(u.BMagenta("WS"), "start")
|
// fmt.Println(u.BMagenta("WS"), "start")
|
||||||
|
|
||||||
if err := ws.connect(vm); err == nil {
|
if err := ws.connect(vm); err == nil {
|
||||||
if ws.pingInterval > 0 {
|
if ws.pingInterval > 0 {
|
||||||
// fmt.Println(u.BMagenta("WS"), "start ping")
|
// fmt.Println(u.BMagenta("WS"), "start ping")
|
||||||
@ -290,10 +291,7 @@ func (hc *Http) Connect(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|||||||
// ws.sleep(time.Duration(ws.pingInterval) * time.Millisecond)
|
// ws.sleep(time.Duration(ws.pingInterval) * time.Millisecond)
|
||||||
for {
|
for {
|
||||||
if ws.conn != nil {
|
if ws.conn != nil {
|
||||||
// fmt.Println(u.BMagenta("WS"), "ping")
|
ws.writeMessage(websocket.PingMessage, nil)
|
||||||
ws.writeLock.Lock()
|
|
||||||
ws.conn.WriteMessage(websocket.PingMessage, []byte{'P'})
|
|
||||||
ws.writeLock.Unlock()
|
|
||||||
}
|
}
|
||||||
if !ws.running {
|
if !ws.running {
|
||||||
break
|
break
|
||||||
@ -310,30 +308,17 @@ func (hc *Http) Connect(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|||||||
ws.pingStopChan <- true
|
ws.pingStopChan <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ws.onMessage != nil || ws.onJSONMessage != nil {
|
if ws.onMessage != nil {
|
||||||
// fmt.Println(u.BMagenta("WS"), "start onMessage")
|
// fmt.Println(u.BMagenta("WS"), "start onMessage")
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
for {
|
for {
|
||||||
if ws.conn != nil {
|
if ws.conn != nil {
|
||||||
if ws.onJSONMessage != nil {
|
typ, data, err := readWSMessage(ws.conn)
|
||||||
var obj interface{}
|
if err != nil {
|
||||||
err := ws.conn.ReadJSON(&obj)
|
break
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
_, _ = ws.onJSONMessage(ws.this, vm.ToValue(obj))
|
|
||||||
} else {
|
|
||||||
typ, buf, err := ws.conn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if typ == websocket.TextMessage {
|
|
||||||
_, _ = ws.onMessage(ws.this, vm.ToValue(string(buf)))
|
|
||||||
} else {
|
|
||||||
_, _ = ws.onMessage(ws.this, vm.ToValue(buf))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_, _ = ws.onMessage(ws.this, vm.ToValue(typ), vm.ToValue(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fmt.Println(u.BMagenta("WS"), "stop onMessage")
|
// fmt.Println(u.BMagenta("WS"), "stop onMessage")
|
||||||
@ -377,8 +362,11 @@ type WS struct {
|
|||||||
onError goja.Callable
|
onError goja.Callable
|
||||||
// onPing goja.Callable
|
// onPing goja.Callable
|
||||||
// onPong goja.Callable
|
// onPong goja.Callable
|
||||||
|
pingTimes int64
|
||||||
|
pongTimes int64
|
||||||
|
lastPingTime int64
|
||||||
|
lastPongTime int64
|
||||||
onMessage goja.Callable
|
onMessage goja.Callable
|
||||||
onJSONMessage goja.Callable
|
|
||||||
pingInterval int64
|
pingInterval int64
|
||||||
reconnectInterval int64
|
reconnectInterval int64
|
||||||
}
|
}
|
||||||
@ -437,6 +425,15 @@ func (ws *WS) connect(vm *goja.Runtime) error {
|
|||||||
// })
|
// })
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
|
ws.pingTimes = 0
|
||||||
|
ws.pongTimes = 0
|
||||||
|
ws.lastPingTime = 0
|
||||||
|
ws.lastPongTime = 0
|
||||||
|
conn.SetPongHandler(func(appData string) error {
|
||||||
|
ws.pongTimes++
|
||||||
|
ws.lastPongTime = time.Now().UnixMilli()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
conn.SetCloseHandler(func(code int, text string) error {
|
conn.SetCloseHandler(func(code int, text string) error {
|
||||||
// fmt.Println(u.BMagenta("WS"), "onClose")
|
// fmt.Println(u.BMagenta("WS"), "onClose")
|
||||||
if ws.onClose != nil {
|
if ws.onClose != nil {
|
||||||
@ -462,48 +459,111 @@ func (ws *WS) connect(vm *goja.Runtime) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WS) Read(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
func (ws *WS) PingCount(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
typ, buf, err := ws.conn.ReadMessage()
|
return vm.ToValue(gojs.Map{
|
||||||
if err != nil {
|
"pingTimes": ws.pingTimes,
|
||||||
panic(vm.NewGoError(err))
|
"pongTimes": ws.pongTimes,
|
||||||
}
|
"lastPingTime": ws.lastPingTime,
|
||||||
if typ == websocket.TextMessage {
|
"lastPongTime": ws.lastPongTime,
|
||||||
return vm.ToValue(string(buf))
|
})
|
||||||
} else {
|
|
||||||
return vm.ToValue(buf)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WS) ReadJSON(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
func (ws *WS) Read(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
var obj interface{}
|
typ, data, err := readWSMessage(ws.conn)
|
||||||
err := ws.conn.ReadJSON(&obj)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(vm.NewGoError(err))
|
panic(vm.NewGoError(err))
|
||||||
}
|
}
|
||||||
return vm.ToValue(obj)
|
return vm.ToValue(gojs.Map{
|
||||||
|
"type": typ,
|
||||||
|
"data": data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func readWSMessage(client *websocket.Conn) (string, any, error) {
|
||||||
|
msgType := "close"
|
||||||
|
var msgData any
|
||||||
|
typ, data, err := client.ReadMessage()
|
||||||
|
if err == nil && typ != websocket.CloseMessage {
|
||||||
|
switch typ {
|
||||||
|
case websocket.TextMessage:
|
||||||
|
if err2 := json.Unmarshal(data, &msgData); err2 != nil {
|
||||||
|
msgData = string(data)
|
||||||
|
msgType = "text"
|
||||||
|
} else {
|
||||||
|
msgType = "json"
|
||||||
|
}
|
||||||
|
case websocket.BinaryMessage:
|
||||||
|
if err2 := json.Unmarshal(data, &msgData); err2 != nil {
|
||||||
|
msgData = data
|
||||||
|
msgType = "binary"
|
||||||
|
} else {
|
||||||
|
msgType = "json"
|
||||||
|
}
|
||||||
|
case websocket.PingMessage:
|
||||||
|
msgData = string(data)
|
||||||
|
msgType = "ping"
|
||||||
|
case websocket.PongMessage:
|
||||||
|
msgData = string(data)
|
||||||
|
msgType = "pong"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msgType, msgData, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WS) writeMessage(typ int, msg []byte) error {
|
||||||
|
ws.writeLock.Lock()
|
||||||
|
defer ws.writeLock.Unlock()
|
||||||
|
if typ == websocket.PingMessage {
|
||||||
|
ws.pingTimes++
|
||||||
|
ws.lastPingTime = time.Now().UnixMilli()
|
||||||
|
}
|
||||||
|
return ws.conn.WriteMessage(typ, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WS) Write(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
func (ws *WS) Write(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
||||||
var err error
|
var err error
|
||||||
ws.writeLock.Lock()
|
switch args.Any(0).(type) {
|
||||||
if args.Arguments[0].ExportType().Kind() == reflect.String {
|
case []byte:
|
||||||
err = ws.conn.WriteMessage(websocket.TextMessage, args.Bytes(0))
|
err = ws.writeMessage(websocket.BinaryMessage, args.Bytes(0))
|
||||||
} else {
|
case string:
|
||||||
err = ws.conn.WriteMessage(websocket.BinaryMessage, args.Bytes(0))
|
err = ws.writeMessage(websocket.TextMessage, args.Bytes(0))
|
||||||
|
default:
|
||||||
|
err = ws.writeMessage(websocket.TextMessage, u.JsonBytes(args.Any(0)))
|
||||||
}
|
}
|
||||||
ws.writeLock.Unlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(vm.NewGoError(err))
|
panic(vm.NewGoError(err))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WS) WriteJSON(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
func (ws *WS) Ping(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
err := ws.writeMessage(websocket.PingMessage, nil)
|
||||||
ws.writeLock.Lock()
|
if err != nil {
|
||||||
err := ws.conn.WriteJSON(args.Any(0))
|
panic(vm.NewGoError(err))
|
||||||
ws.writeLock.Unlock()
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WS) WriteMessage(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
||||||
|
var err error
|
||||||
|
switch args.Str(0) {
|
||||||
|
case "text":
|
||||||
|
err = ws.writeMessage(websocket.TextMessage, args.Bytes(1))
|
||||||
|
case "binary":
|
||||||
|
err = ws.writeMessage(websocket.BinaryMessage, args.Bytes(1))
|
||||||
|
case "ping":
|
||||||
|
err = ws.writeMessage(websocket.PingMessage, args.Bytes(1))
|
||||||
|
case "pong":
|
||||||
|
err = ws.writeMessage(websocket.PongMessage, args.Bytes(1))
|
||||||
|
case "close":
|
||||||
|
err = ws.writeMessage(websocket.CloseMessage, args.Bytes(1))
|
||||||
|
case "json":
|
||||||
|
err = ws.writeMessage(websocket.TextMessage, u.JsonBytes(args.Any(1)))
|
||||||
|
default:
|
||||||
|
err = ws.writeMessage(websocket.TextMessage, args.Bytes(1))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(vm.NewGoError(err))
|
panic(vm.NewGoError(err))
|
||||||
}
|
}
|
||||||
|
22
http.ts
22
http.ts
@ -59,16 +59,28 @@ interface WSConfig {
|
|||||||
compress: boolean
|
compress: boolean
|
||||||
onOpen: () => void
|
onOpen: () => void
|
||||||
onClose: (code: number, data: string) => void
|
onClose: (code: number, data: string) => void
|
||||||
onMessage: (data: any) => void
|
onMessage: (type: string, data: any) => void
|
||||||
onJSONMessage: (data: any) => void
|
|
||||||
pingInterval: number
|
pingInterval: number
|
||||||
reconnectInterval: number
|
reconnectInterval: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WS {
|
interface WS {
|
||||||
read(): any
|
read: () => WSMessage
|
||||||
readJSON(): any
|
|
||||||
write(data: any): void
|
write(data: any): void
|
||||||
writeJSON(data: any): void
|
writeMessage(type: string, data: any): void
|
||||||
|
ping: () => void
|
||||||
|
pingCount: () => PingCount
|
||||||
close(): void
|
close(): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PingCount {
|
||||||
|
pingTimes: number
|
||||||
|
pongTimes: number
|
||||||
|
lastPingTime: number
|
||||||
|
lastPongTime: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WSMessage {
|
||||||
|
type: string
|
||||||
|
data: string | Object
|
||||||
|
}
|
||||||
|
29
ws_test.js
29
ws_test.js
@ -6,20 +6,21 @@ function main() { }
|
|||||||
function testSync() {
|
function testSync() {
|
||||||
let conn = http.connect("http://127.0.0.1:18001/ws")
|
let conn = http.connect("http://127.0.0.1:18001/ws")
|
||||||
conn.write('111')
|
conn.write('111')
|
||||||
if (conn.read() !== '111') {
|
let r1 = conn.read().data
|
||||||
return false
|
if (r1 !== 111) {
|
||||||
|
return r1
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.write(new Uint8Array([0x01, 0x02, 0x03]))
|
conn.write(new Uint8Array([0x01, 0x02, 0x03]))
|
||||||
let r2 = conn.read()
|
let r2 = conn.read().data
|
||||||
if (r2[0] != 1 || r2[1] != 2 || r2[2] != 3) {
|
if (r2[0] != 1 || r2[1] != 2 || r2[2] != 3) {
|
||||||
return false
|
return r2
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.writeJSON({ name: 'Tom' })
|
conn.write({ name: 'Tom' })
|
||||||
let r3 = conn.readJSON()
|
let r3 = conn.read().data
|
||||||
if (r3.name != 'Tom') {
|
if (r3.name != 'Tom') {
|
||||||
return false
|
return r3
|
||||||
}
|
}
|
||||||
conn.close()
|
conn.close()
|
||||||
return true
|
return true
|
||||||
@ -42,22 +43,22 @@ function testAsync() {
|
|||||||
onPong: function (data) {
|
onPong: function (data) {
|
||||||
console.info("onPong", data)
|
console.info("onPong", data)
|
||||||
},
|
},
|
||||||
onJSONMessage: function (data) {
|
onMessage: function (type, data) {
|
||||||
// console.info("onJSONMessage", data)
|
// console.info("onJSONMessage", data)
|
||||||
asyncResult += data.name
|
asyncResult += data.name
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
asyncConn = conn
|
asyncConn = conn
|
||||||
|
|
||||||
conn.writeJSON({ name: 'Tom1' })
|
conn.write({ name: 'Tom1' })
|
||||||
conn.writeJSON({ name: 'Tom2' })
|
conn.write({ name: 'Tom2' })
|
||||||
conn.writeJSON({ name: 'Tom3' })
|
conn.write({ name: 'Tom3' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAsync2() {
|
function testAsync2() {
|
||||||
asyncConn.writeJSON({ name: 'Tom4' })
|
asyncConn.write({ name: 'Tom4' })
|
||||||
asyncConn.writeJSON({ name: 'Tom5' })
|
asyncConn.write({ name: 'Tom5' })
|
||||||
asyncConn.writeJSON({ name: 'Tom6' })
|
asyncConn.write({ name: 'Tom6' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeAsync() {
|
function closeAsync() {
|
||||||
|
Loading…
Reference in New Issue
Block a user