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