duanjiati1755 2019-09-07 17:28
浏览 249

syscall / js websocket回调在非阻塞行为中不响应

I have two processes running, written in Go in which one (sender.go) sends a message to another (listener.go) while being stuck in a for loop via websockets.

The issue is that listener.go only realizes it received the message after it terminates the loop.

I have tried several websocket libraries, I even tried using regular tcp streams, but it won't work when compiled in webassembly because browser won't support it. The syscall/js websocket seemed to be the perfect fit despite this behaviour.

here's listener.go

func registerCallbacks(ws js.Value) {
    ws.Call("addEventListener", "message", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        message := args[0].Get("data").String()
        fmt.Println("message received ")
        fmt.Println(message)
        return nil
    }))
}


func main() {
    c := make(chan struct{}, 0)
    toIP := "127.0.0.1"
    toPort := 8081
    ws := js.Global().Get("WebSocket").New(fmt.Sprintf("ws://%s:%d/ws", toIP, toPort))
    registerCallbacks(ws)
    const bigNum uint64 = 100000 * 10000
    cb := func(this js.Value, args []js.Value) interface{} {
      for i := uint64(0); i < bigNum; i++ {
        doThings()
        if i%10000000 == 0 {
            fmt.Println("skimmed ten millions ")
        }
      }
      fmt.Println("Exited for loop !!")
      return nil
    }
    // call cb() in script of index.html from a button
    js.Global().Set("cb", js.FuncOf(cb))
    <-c
}

So is sender.go,

func main() {
    toIP := "127.0.0.1"
    toPort := 8081
    ws := js.Global().Get("WebSocket").New(fmt.Sprintf("ws://%s:%d/ws", toIP, toPort))
    time.Sleep(1 * time.Second)
    fmt.Println("sending  ")
    ws.Call("send", js.ValueOf("msg"))
    fmt.Println("Program exit  ")
}

If someone's willing to reproduce the issue here's the websocket server which receives message from sender to forward it to receiver, written in node.js, just copy and paste this, it works fine with several projects

const port = 8081;
const host = '127.0.0.1';

var WebSocketServer = require('websocket').server;
var http = require('http');

var server = http.createServer(function(request, response) {});

server.listen(port, host, () => {
    console.log('WS Server is running on port ' + port + '.');
});

wsServer = new WebSocketServer({
    httpServer: server
});

let sockets = [];


wsServer.on('request', function(request) {
  var connection = request.accept(null, request.origin);
  sockets.push(connection)
  console.log("Connection with node initiated")
  connection.on('message', function(message) {
    console.log("message received "+message)
    sockets.forEach(function(s, index, array) {
      if (message.type === 'utf8') {
        broadcastData = message.utf8Data
        console.log("message is: "+ broadcastData)
        if(s!= connection) {
          console.log('send data to ' + s.socket.remotePort + ': ' + broadcastData);
          s.sendUTF(broadcastData)
        }
      }
    });
  });
});

I am expecting listener.go to receive message before it exits the for loop

PS: Using sleep statement is not a good help , because when this for loop runs inside a js callback, the sleep statement outputs a panic.

  • 写回答

1条回答 默认 最新

  • dragon8997474 2019-09-07 21:05
    关注

    First, note that if you are generating wasm Go code, it's not multi-threaded, at least not today (September 2019). See How to implement multithreading in wasm created using golang? So there's only one actual execution thread.

    Then, remember that goroutines are cooperatively multi-tasked onto whatever threads are available. Since there's only one thread, there's only one goroutine running at any time. If your running goroutine does not give up the processor to other goroutines, those other goroutines won't run.

    You can give up the processor implicitly—for instance, by waiting on a channel or a mutex—or explictly, via time.Sleep or runtime.Gosched. Without such a call, any goroutine that would notice the incoming message never gets a chance to see it, and your callback—which will run in this or some third goroutine—never gets called.

    (If you run natively, rather than in wasm, you will generally get more threads and will be able to have other CPUs run other tasks even while one is in a tight loop.)

    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料