2017-06-19 388 views

回答

4

示例代码连接到公共回声Web套接字服务器, 发送消息,接收响应并断开连接。

JavaScript代码提供web套接字和日志记录到webassembly代码的功能。

主程序逻辑用C编写,然后编译成wasm文件。

结果可以在js控制台中看到。

汇编:

EMCC ws_test.c -o ws_test.html -O1 -s WASM = 1 -s ONLY_MY_CODE = 1 -s EXPORTED_FUNCTIONS =“[ '_的GetBuffer', '_ wsOnMessage', '_wsOnOpen', '_test']“

结果文件ws_test.wasm很小。 (431个字节)

要检查WASM可以被反编译到可读s表达式的条件:
wasm2wast ws_test.wasm -o ws_test.wast

ws_test.c

extern void wsConnect(char *address); 
    extern void wsSend(char *message); 
    extern void wsClose(); 
    extern void print(char *message); 

    char buffer[100]; 
    char *getBuffer(){ return buffer; } 

    void wsOnMessage(){ 
     print("received message"); 
     print(buffer); 
     wsClose(); 
     print("connection closed"); 
    } 

    void wsOnOpen(){ 
     print("connected"); 
     wsSend("Hello WebAssembly !"); 
    } 


    void test(){ 
     wsConnect("ws://echo.websocket.org"); 
     print("connecting..."); 
    } 

ws_test.html

 <script> 

     var webSocket; 
     const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 }); 
     const buffer = new Uint8Array(memory.buffer); 
     var exports; 

     function toJsStr(offset){ 
      var s=""; 
      for(;;){ 
       var b = buffer[offset++]; 
       if(b == 0) 
        return s; 
      s += String.fromCharCode(b); 
     } 
     } 
     function toCStr(str){ 
     var offset = exports._getBuffer(); 
     for (var i = 0; i < str.length; ++i) { 
      buffer[offset++] = str.charCodeAt(i); 
     } 
     buffer[offset] = 0; 
     } 

     function print(offset){ 
     console.log(toJsStr(offset)); 
     } 

     function wsConnect(offset){ 
     webSocket = new WebSocket(toJsStr(offset)); 
     webSocket.onopen = function(){ 
      console.log("Socket is open"); 
      exports._wsOnOpen(); 
     }; 

     webSocket.onmessage = function (evt){ 
      var msg = evt.data; 
      console.log("Message is received..."); 
      toCStr(msg); 
      exports._wsOnMessage(); 
     }; 
     } 

     function wsClose(){ 
     webSocket.close(); 
     } 

     function wsSend(offset){ 
     webSocket.send(toJsStr(offset)); 
     } 

     fetch('ws_test.wasm').then(response => 
     response.arrayBuffer() 
    ).then(bytes => { 
      var imports = {}; 
      imports.env = {}; 
      imports.env.memory = memory; 
      imports.env.memoryBase = 0; 
      imports.env.table = new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' }); 
      imports.env.tableBase = 0; 
      imports.env._print = print; 
      imports.env._wsConnect = wsConnect; 
      imports.env._wsSend = wsSend; 
      imports.env._wsClose = wsClose; 


      return WebAssembly.instantiate(bytes, imports); 
     } 
    ).then(module => { 
      exports = module.instance.exports; 

      exports._test(); 
      } 
    ); 
     </script> 

在这里使用的编译器标记“ONLY_MY_CODE = 1”,所以结果WASM将非常小, 和不链接到任何标准库

如果模块用于算术计算该模式是方便的。

所以你不能在模式下使用:printf,malloc/free,strcpy!

如果您错过了字符串函数:strcpy,strcat,strlen ... - 您可以将函数源添加到代码中。

但是,如果你需要例如malloc/free更好的链接标准C库。

0

它只是演示,而不是产品。

  • toJsStr(偏移量)和toCStr(STR)可以支持UTF-8(目前仅ASCII)

  • toCStr应该使用不仅缓冲区偏移,而且缓冲区大小,以防止 缓冲区溢出。

  • 错过的通讯错误处理:应使用web套接字回调: 的onerror()的OnClose()