网络

    以下是一个使用 JavaScript 编写的异步客户端的例子。你可以在 中找到源码。以下的代码会向你展示如何发送一个异步 HTTP GET 请求。

    以上代码可以在等待服务端应答的同时处理其他任务。当服务端返回数据后, 会被异步调用,处理好数据后就会将内容打印出来。

    1. async function handle_response(s) {
    2. let buf = new http.Buffer();
    3. let resp = undefined;
    4. while (true) {
    5. buf.append(await s.read());
    6. if (resp == undefined) {
    7. resp = buf.parseResponse();
    8. }
    9. if (resp instanceof http.WasiResponse) {
    10. let resp_length = resp.bodyLength;
    11. if (typeof (resp_length) === "number") {
    12. if (buf.length >= resp.bodyLength) {
    13. print('resp.body');
    14. print(newStringFromUTF8(buf.buffer));
    15. break;
    16. }
    17. } else {
    18. throw new Error('no support');
    19. }
    20. }
    21. }
    22. }

    使用以下 CLI 命令,就可以在 WasmEdge runtime 中运行以上的 JavaScript 代码。

    1. cd example_js
    2. wasmedge --dir .:. ../target/wasm32-wasi/release/wasmedge_quickjs.wasm wasi_http_client.js

    以上应用例子发出了两个 HTTP 请求,一个是 GET 请求另一个是 POST 请求。该应用会异步等待这两个请求的应答数据,并且哪一个先从服务端返回就先会处理哪个。从日志中你可以看到这两个请求的 handlers 是交错执行的。

    以下的例子是使用 JavaScript 运行了一个监听 8000 端口的 TCP 服务器。接收到的网络请求都会被异步处理。你可以在 example_js/wasi_net_echo.js 中找到源码。

    1. import * as net from 'wasi_net';
    2. async function handle_client(cs) {
    3. while (true) {
    4. try {
    5. let d = await cs.read();
    6. if (d.byteLength <= 0) {
    7. break;
    8. }
    9. cs.write('echo:' + s);
    10. } catch (e) {
    11. }
    12. }
    13. }
    14. async function server_start() {
    15. let s = new net.WasiTcpServer(8000);
    16. for (var i = 0; i < 100; i++) {
    17. let cs = await s.accept();
    18. handle_client(cs);
    19. }
    20. }
    21. server_start();

    调用 server_start() 方法会在 8000 端口启动一个监听服务。当一个请求进入,会异步传给 handle_client() function 函数处理。这意味着当应用返回应答数据后,它又可以处理下一个进来的请求了。

    使用以下 CLI 命令,就可以在 WasmEdge runtime 中运行这段 JavaScript 代码。因为它将作为一个服务运行,你最好是以后台应用的形式启动。

    1. cd example_js
    2. nohup wasmedge --dir .:. ../target/wasm32-wasi/release/wasmedge_quickjs.wasm wasi_net_echo.js &

    WasmEdge 的 wasi_net 包为 JavaScript 应用提供了一种自适应的动态网络栈。在很多高级用法中,我们基于这个包,设计了很多抽象良好的 API。在下一章节,我们会带着具体的常见应用,向你展示如何处理 HTTP 请求。在 中,我们还将会讨论一下如何基于这种异步网络的 API 来创建一个 React 服务器渲染功能。

    假如你已经知道服务器的请问和应答都是基于 HTTP 协议的,这里有一些增强方法可以帮到你更好地处理这些请求。你可以在 example_js/wasi_http_echo.js 中找到源码。

    1. import * as http from 'wasi_http';
    2. import * as net from 'wasi_net';
    3. async function handle_client(cs, handler_req) {
    4. let buffer = new http.Buffer();
    5. while (true) {
    6. try {
    7. let d = await cs.read();
    8. if (d.byteLength <= 0) {
    9. return;
    10. }
    11. buffer.append(d);
    12. let req = buffer.parseRequest();
    13. if (req instanceof http.WasiRequest) {
    14. handler_req(cs, req);
    15. break;
    16. }
    17. print(e);
    18. }
    19. }
    20. function handler_req(cs, req) {
    21. print("version=", req.version);
    22. print("uri=", req.uri);
    23. print("method=", req.method);
    24. print("headers=", Object.keys(req.headers));
    25. print("body=", newStringFromUTF8(req.body));
    26. let resp = new http.WasiResponse();
    27. let body = 'echo:' + newStringFromUTF8(req.body);
    28. let r = resp.encode(body);
    29. cs.write(r);
    30. }
    31. async function server_start() {
    32. try {
    33. let s = new net.WasiTcpServer(8000);
    34. for (var i = 0; i < 100; i++) {
    35. let cs = await s.accept();
    36. try {
    37. handle_client(cs, handler_req);
    38. } catch (e) {
    39. print(e);
    40. }
    41. }
    42. } catch (e) {
    43. print(e);
    44. }
    45. }
    46. server_start();

    server_start() 方法会启动一个监听 8000 端口的服务。当请求进来,会被传给 handle_client() 方法来处理。当请求是合法的 HTTP 请求,对应的 handler 方法会调用 handle_req() 来解析对应的字段,组装新的 HTTP 应答,然后异步把应答数据发送回去。这意味着当应用发送完数据,又能继续处理下一个进来的请求了。

    使用以下 CLI 命令,就可以在 WasmEdge runtime 中运行这段 JavaScript 代码。因为它将作为一个服务运行,你最好是以后台应用的形式运行。

    1. cd example_js

    在异步 HTTP 网络编程中,开发者可以安全并高效地在 WasmEdge 中使用 JavaScript 创建强交互的应用,例如数据库驱动的微服务。