{"id":1010,"date":"2026-08-27T15:33:59","date_gmt":"2026-08-27T15:33:59","guid":{"rendered":"https:\/\/boochlin.com\/?p=1010"},"modified":"2026-08-27T15:33:59","modified_gmt":"2026-08-27T15:33:59","slug":"android-%e7%88%9b%e8%a3%9d%e7%bd%ae%e6%83%b3%e8%b7%91%e4%ba%ba%e8%87%89%e8%be%a8%e8%ad%98-%e7%ac%ac-12-%e7%af%87-%e8%aa%aa%e5%88%b0%e5%ba%95%e9%82%84%e6%98%af%e4%b8%80%e5%8f%b0iot","status":"publish","type":"post","link":"https:\/\/boochlin.com\/?p=1010","title":{"rendered":"Android \u721b\u88dd\u7f6e\u60f3\u8dd1\u4eba\u81c9\u8fa8\u8b58 \u7b2c 12 \u7bc7 &#8211; \u8aaa\u5230\u5e95\u9084\u662f\u4e00\u53f0IOT"},"content":{"rendered":"\n<blockquote class=\"wp-block-quote\">\n<p><strong>\u300c\u5728\u767e\u5143\u7d1a\u9580\u7981\u6a5f\u4e0a\u505a\u7db2\u8def\u901a\u8a0a\uff0c\u6700\u5929\u771f\u7684\u60f3\u6cd5\u5c31\u662f\u4ee5\u70ba\u7db2\u8def\u6c38\u9060\u5f88\u9806\uff1b\u771f\u6b63\u7684\u5de5\u696d\u7d1a\u67b6\u69cb\uff0c\u662f\u628a\u6bcf\u4e00\u5929\u90fd\u7576\u4f5c\u300e\u96a8\u6642\u6703\u65b7\u7db2\u3001\u96a8\u6642\u6703\u88ab\u62d4\u63d2\u982d\u300f\u7684\u4e16\u754c\u672b\u65e5\u4f86\u8a2d\u8a08\u3002\u300d<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243.jpg\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"572\" src=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243-1024x572.jpg\" alt=\"\" class=\"wp-image-1011\" srcset=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243-1024x572.jpg 1024w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243-300x167.jpg 300w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243-768x429.jpg 768w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/blog12_breaking_bad_cartoon_1787842240243.jpg 1376w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/blockquote>\n\n\n\n<p>\u524d\u9762\u5e7e\u7bc7\u6211\u5011\u628a\u9ad8\u901a\u9a4d\u9f8d QM215\uff084 \u9846 A53\u30012GB RAM\uff09\u7684\u7cfb\u7d71\u7626\u8eab\u8207\u76f8\u6a5f\u96f6\u62f7\u8c9d\u69a8\u5230\u4e86\u6975\u81f4\u3002\u4f46\u7576\u9580\u7981\u6a5f\u639b\u4e0a\u5de5\u5ee0\u5927\u9580\u6642\uff0c\u73fe\u5834\u7684\u7db2\u8def\u6bd4\u6676\u7247\u66f4\u6158\uff1a\u8a2d\u5099\u8eb2\u5728\u4f01\u696d\u5167\u7db2\u6df1\u8655\uff08<code>192.168.1.X<\/code> \u7121\u516c\u7db2 IP\uff09\u3001\u7db2\u8def\u7dda\u96a8\u6642\u88ab\u62d4\u3001DNS \u52d5\u8f12\u5361\u6b7b 30 <strong>\u5728\u908a\u7de3 IoT \u7cfb\u7d71\u4e2d\uff0cWebSocket \u8207 RESTful API \u5230\u5e95\u8a72\u5982\u4f55\u7cbe\u6e96\u5206\u5de5\uff0c\u505a\u5230\u300c0.1 \u79d2\u5373\u6642\u958b\u9580\u3001\u96f6\u8a18\u61b6\u9ad4\u8ca0\u64d4\u3001\u65b7\u7db2 3 \u5929\u4e5f\u80fd\u7a69\u5065\u91cd\u9023\u300d\uff01<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928.jpg\"><img decoding=\"async\" width=\"1024\" height=\"572\" data-id=\"1012\" src=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928-1024x572.jpg\" alt=\"\" class=\"wp-image-1012\" srcset=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928-1024x572.jpg 1024w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928-300x167.jpg 300w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928-768x429.jpg 768w, https:\/\/boochlin.com\/wp-content\/uploads\/2026\/08\/iot_dual_arch_zh_1787841845928.jpg 1376w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e00\u3001 \u70ba\u4ec0\u9ebc\u5fc5\u9808\u7528 WebSocket\uff1f<\/h2>\n\n\n\n<p>\u5728\u908a\u7de3\u8a2d\u5099\u4e2d\uff0cHTTP \u77ed\u8f2a\u8a62\uff08Polling\uff09\u5728\u5de5\u5ee0\u73fe\u5834\u6703\u7acb\u523b\u9047\u5230\u5169\u5927\u6b7b\u7a74\uff1a<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. \u5ef6\u9072\u8207\u4f3a\u670d\u5668\u7576\u6a5f\u7684\u6b7b\u5faa\u74b0<\/h3>\n\n\n\n<ul>\n<li><strong>5 \u79d2\u8f2a\u8a62<\/strong>\uff1a\u8a2a\u5ba2\u6309\u9234\u5e73\u5747\u4e7e\u7b49 2.5 \u79d2\uff0c\u9ad4\u9a57\u6975\u5dee\uff1b<\/li>\n\n\n\n<li><strong>200ms \u8f2a\u8a62<\/strong>\uff1a\u5168\u5ee0 100 \u53f0\u8a2d\u5099\u6bcf\u79d2\u7522\u751f 500 \u6b21\u8acb\u6c42\uff0c\u9ad8\u9054 4 \u500b RTT \u7684 TCP\/TLS \u63e1\u624b\u77ac\u9593\u6253\u7206\u5730\u7aef\u5c0f\u4f3a\u670d\u5668\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u5167\u7db2 NAT \u7a7f\u900f\u56f0\u5883<\/h3>\n\n\n\n<p>\u9580\u7981\u6a5f\u7121\u516c\u7db2 IP\uff0c\u96f2\u7aef\u4f3a\u670d\u5668\u5b8c\u5168\u7121\u6cd5\u4e3b\u52d5\u767c\u8d77 HTTP POST \u767c\u9001\u958b\u9580\u6307\u4ee4\u3002\u8a2d\u5099\u5fc5\u9808\u5728\u958b\u6a5f\u6642\u4e3b\u52d5\u5411\u4f3a\u670d\u5668\u5efa\u7acb WebSocket \u9577\u9023\u7dda\uff0c\u5728\u9632\u706b\u7246\u4e0a\u947f\u51fa\u6c38\u4e45\u96d9\u5411\u901a\u9053\uff08Pinhole\uff09\uff1a<\/p>\n\n\n\n<ul>\n<li><strong>\u4e0b\u884c\u5373\u6642\u63a7\u5236<\/strong>\uff1a0.1 \u79d2\u9060\u7aef\u958b\u9580\u3001\u5373\u6642\u8a3b\u92b7\u96e2\u8077\u54e1\u5de5\u3001\u8a2a\u5ba2\u52d5\u614b\u5bc6\u78bc\u9a57\u8b49\uff1b<\/li>\n\n\n\n<li><strong>\u4e0a\u884c\u5373\u6642\u56de\u5831<\/strong>\uff1a\u5237\u81c9\u6253\u5361\u6293\u62cd\u7167\u5373\u6642\u4e0a\u50b3\u3001\u9632\u62c6\u6a5f\u8b66\u5831\uff1b<\/li>\n\n\n\n<li><strong>\u901a\u9053\u4fdd\u6d3b<\/strong>\uff1a15 \u79d2\u8f15\u91cf\u5fc3\u8df3\u7dad\u6301\u9632\u706b\u7246\u901a\u9053\u66a2\u901a\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e8c\u3001 \u70ba\u4ec0\u9ebc\u5927\u6a94\u6848\u4e0d\u80fd\u9032 WebSocket\uff1fRESTful API \u7684\u4e0d\u53ef\u66ff\u4ee3\u6027<\/h2>\n\n\n\n<p>\u5982\u679c\u628a\u6240\u6709\u529f\u80fd\u5168\u90e8\u585e\u9032 WebSocket\uff0c\u73fe\u5834\u6703\u7acb\u523b\u5f15\u767c\u56b4\u91cd\u7684\u958b\u9580\u5361\u6b7b\u4e8b\u6545\u3002RESTful API \u6709\u5176\u5c08\u5c6c\u6230\u5834\uff1a<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. \u7b2c\u4e09\u65b9\u7cfb\u7d71\uff08SAP \/ HR \u8003\u52e4\uff09\u6a19\u6e96\u7121\u7e2b\u5c0d\u63a5<\/h3>\n\n\n\n<p>\u7531\u4f3a\u670d\u5668\u63d0\u4f9b\u6a19\u6e96 RESTful API\uff08\u5982 <code>POST \/api\/v1\/users<\/code> \u65b0\u589e\u54e1\u5de5\u3001<code>GET \/api\/v1\/events<\/code> \u6279\u6b21\u532f\u51fa\uff09\uff0c\u5ba2\u6236\u7528\u6700\u719f\u6089\u7684 HTTP \u5373\u53ef\u4e32\u63a5\uff0c\u7121\u9700\u5728\u4ed6\u5011\u7684\u7cfb\u7d71\u7dad\u8b77\u8106\u5f31\u7684\u9577\u9023\u7dda\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. 50MB \u97cc\u9ad4\u5347\u7d1a\u8207\u5927\u6a94\u6848\u4e0b\u8f09<\/h3>\n\n\n\n<p>50MB APK \u66f4\u65b0\u6a94\u30013D \u93e1\u982d\u97cc\u9ad4\u8207\u9ad8\u89e3\u6790\u5ea6\u7167\u7247\u6279\u6b21\u4e0b\u8f09\uff0c\u5fc5\u9808\u8d70\u6a19\u6e96 HTTP \u9032\u884c\u5206\u6bb5\u6d41\u5f0f\u50b3\u8f38\u8207\u65b7\u9ede\u7e8c\u50b3\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u9632\u79a6 TCP \u968a\u982d\u963b\u585e\uff08\u9ad8\u901f\u516c\u8def\u585e\u8eca\u6548\u61c9\uff09<\/h3>\n\n\n\n<p>WebSocket \u5e95\u5c64\u70ba\u55ae\u4e00 TCP \u9023\u7dda\u3002\u82e5\u5c07 50MB \u97cc\u9ad4\u585e\u9032 WebSocket\uff0c\u6703\u77ac\u9593\u4f54\u6eff\u6574\u689d\u9023\u7dda\uff1b\u6b64\u6642\u82e5\u7a81\u767c\u300c\u7dca\u6025\u958b\u9580\u300d\u6307\u4ee4\uff0c<strong>\u958b\u9580\u5c01\u5305\u88ab\u8feb\u6392\u5728 50MB \u6a94\u6848\u5f8c\u9762\u7b49\u5e7e\u5341\u79d2<\/strong>\uff0c\u5c0e\u81f4\u9580\u6253\u4e0d\u958b\uff01<br><strong>\u5c07\u300c\u5927\u6a94\u6848\u50b3\u8f38\uff08HTTP REST\uff09\u300d\u8207\u300c\u5373\u6642\u4fe1\u4ee4\uff08WebSocket\uff09\u300d\u7269\u7406\u9694\u96e2\uff0c\u662f\u4fdd\u8b49 0.1 \u79d2\u79d2\u958b\u9580\u7684\u95dc\u9375\u5e95\u7dda\u3002<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e09\u3001 \u8cc7\u6599\u50b3\u8f38\u5927\u7626\u8eab\uff1a\u70ba\u4f55\u9078\u300cProtobuf over WebSocket\u300d\uff1f<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Base64 \u8b93\u8a18\u61b6\u9ad4\u76f4\u63a5\u7206\u6389<\/h3>\n\n\n\n<p>\u65e9\u671f\u5c07\u73fe\u5834\u7167\u7247\u8f49\u70ba Base64 \u5b57\u4e32\u585e\u9032 JSON \u50b3\u8f38\uff1a<\/p>\n\n\n\n<ul>\n<li>\u9ad4\u7a4d\u81a8\u8139 33%\uff0c\u6d6a\u8cbb\u983b\u5bec\uff1b<\/li>\n\n\n\n<li>\u4e00\u5f35 150KB JPEG \u8f49\u6210 Base64 \u6703\u5728 Java \u8a18\u61b6\u9ad4\u7522\u751f 200KB \u7684 String \u5783\u573e\u3002\u5c16\u5cf0\u671f\u983b\u7e41\u89f8\u767c\u5783\u573e\u56de\u6536\uff08GC\uff09\uff0c\u76f8\u6a5f\u9810\u89bd\u76f4\u63a5\u5f9e 30fps \u6389\u5230\u500b\u4f4d\u6578\u5c0e\u81f4\u4eba\u81c9\u4e1f\u5e40\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u70ba\u4ec0\u9ebc\u4e0d\u76f4\u63a5\u4e0a\u5168\u5957 gRPC\uff1f\uff08Web \u700f\u89bd\u5668\u76f4\u9023\u786c\u50b7\uff09<\/h3>\n\n\n\n<ul>\n<li><strong>\u700f\u89bd\u5668\u5929\u7136\u9650\u5236<\/strong>\uff1a\u8b66\u885b\u5ba4 Chrome \u5927\u87a2\u5e55\u9700\u770b\u5373\u6642\u901a\u884c\u3002\u6839\u64da W3C \u6a19\u6e96\uff0c\u700f\u89bd\u5668 JS \u7121\u6cd5\u53d6\u5f97 HTTP\/2 \u5e95\u5c64 Framing \u8207 gRPC \u4f9d\u8cf4\u7684 <code>Trailers<\/code>\uff08\u5c3e\u96a8\u6a19\u982d\uff09\uff0c<strong>Chrome \u6c38\u9060\u7121\u6cd5\u539f\u751f\u76f4\u9023 gRPC<\/strong>\uff1b<\/li>\n\n\n\n<li><strong>Envoy \u7dad\u904b\u707d\u96e3<\/strong>\uff1a\u82e5\u786c\u4e0a gRPC\uff0c\u5fc5\u9808\u5728\u5730\u7aef\u6a5f\u623f\u984d\u5916\u67b6\u8a2d Envoy Proxy \u4f3a\u670d\u5668\u505a\u8f49\u8b6f\uff0c\u591a\u4e00\u500b\u7d44\u4ef6\u5c31\u591a\u4e00\u500b\u7576\u6a5f\u9ede\uff1b<\/li>\n\n\n\n<li><strong>\u8001\u820a\u9632\u706b\u7246\u5730\u96f7<\/strong>\uff1a\u4f01\u696d\u5167\u7db2\u8001\u820a\u4ee3\u7406\u5c0d HTTP\/2 \u4e8c\u9032\u4f4d\u591a\u5de5\u4e32\u6d41\u652f\u63f4\u6975\u5dee\uff0c\u5e38\u8aa4\u5224\u70ba\u653b\u64ca\u76f4\u63a5\u6390\u65b7\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u6700\u4f73\u89e3\u7b54\uff1aProtobuf over WebSocket \u5168\u68e7\u5927\u4e00\u7d71<\/h3>\n\n\n\n<p>\u7dad\u6301\u55ae\u4e00 8082 WebSocket \u57e0\u865f\uff0cPayload \u5168\u9762\u63db\u6210 Google Protocol Buffers\uff1a<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsyntax = &quot;proto3&quot;;\npackage com.kuke.gate;\n\nmessage PassEventPacket {\n  string device_id = 1;\n  int64 timestamp = 2;\n  string user_id = 3;\n  bool is_authorized = 4;\n\n  \/\/ \u539f\u751f\u4e8c\u9032\u4f4d byte \u9663\u5217\u76f4\u5165\uff0c0 Base64\u30010 \u984d\u5916\u5b57\u4e32\u8a18\u61b6\u9ad4\u5783\u573e\uff01\n  bytes rgb_image = 5;\n  bytes ir_image = 6;\n  bytes depth_image = 7;\n}\n<\/pre><\/div>\n\n\n<ul>\n<li><strong>\u9580\u7981\u6a5f\u7aef<\/strong>\uff1aJPEG \u4f4d\u5143\u7d44\u76f4\u63a5\u585e\u9032 Protobuf\uff0cJava \u8a18\u61b6\u9ad4\u5783\u573e\u6b78\u96f6\uff0c\u5c01\u5305\u6bd4 JSON \u5c0f 60%\uff1b<\/li>\n\n\n\n<li><strong>\u8b66\u885b\u5ba4 Web \u7aef<\/strong>\uff1aChrome \u700f\u89bd\u5668\u539f\u751f <code>new WebSocket()<\/code> \u76f4\u9023\uff0c\u639b\u8f09 <code>protobuf.js<\/code> \u4e00\u884c\u4ee3\u78bc\u89e3\u78bc\uff0c<strong>\u96f6 Envoy \u4ee3\u7406\u4f9d\u8cf4\uff01<\/strong><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u56db\u3001 \u908a\u7de3\u88dd\u7f6e\u7684\u7a69\u5b9a\u6027\u5be6\u6230\uff1a\u4e3b\u6d41\u8a2d\u8a08\u600e\u9ebc\u505a\uff1f<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. HandlerThread \u55ae\u57f7\u884c\u7dd2\u4e8b\u4ef6\u6392\u968a<\/h3>\n\n\n\n<p>\u7db2\u8def\u9023\u7dda\uff08DNS \u89e3\u6790\u3001TCP \u63e1\u624b\u3001\u5fc3\u8df3\uff09\u4ea4\u7531\u5c08\u5c6c <code>HandlerThread<\/code> \u5728\u80cc\u666f\u55ae\u884c\u9053\u4f9d\u5e8f\u6392\u968a\uff1a<\/p>\n\n\n\n<ul>\n<li><strong>UI \u96f6\u5ef6\u9072<\/strong>\uff1aUI \u547c\u53eb\u50c5\u4e1f Message \u6392\u968a\uff0c0.01ms \u7acb\u523b\u8fd4\u56de\uff1b<\/li>\n\n\n\n<li><strong>\u5167\u90e8\u72c0\u614b\u5c01\u9589<\/strong>\uff1aSocket \u5be6\u9ad4\u5b8c\u5168\u5c01\u88dd\u5728\u80cc\u666f\u57f7\u884c\u7dd2\u4e2d\uff0c\u514d\u9664\u8907\u96dc\u8de8\u57f7\u884c\u7dd2\u52a0\u9396\u3002<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npublic class WebSocketWorkerManager {\n    private static final int MSG_CONNECT = 1;\n    private static final int MSG_SEND_EVENT = 2;\n    private static final int MSG_HEARTBEAT = 3;\n\n    private final HandlerThread workerThread;\n    private final Handler workerHandler;\n    private final AtomicBoolean isConnected = new AtomicBoolean(false);\n    private WebSocketClient webSocketClient;\n\n    public WebSocketWorkerManager() {\n        workerThread = new HandlerThread(&quot;WebSocket-Worker&quot;);\n        workerThread.start();\n        workerHandler = new Handler(workerThread.getLooper()) {\n            @Override\n            public void handleMessage(@NonNull Message msg) {\n                switch (msg.what) {\n                    case MSG_CONNECT:\n                        handleConnect((String) msg.obj);\n                        break;\n                    case MSG_SEND_EVENT:\n                        handleSendEvent((byte&#x5B;]) msg.obj);\n                        break;\n                    case MSG_HEARTBEAT:\n                        handleHeartbeat();\n                        break;\n                }\n            }\n        };\n    }\n\n    \/** UI \u547c\u53eb\uff1a\u50c5\u4e1f Message \u6392\u968a\uff0c0.01ms \u8fd4\u56de *\/\n    public void connect(String serverUrl) {\n        workerHandler.obtainMessage(MSG_CONNECT, serverUrl).sendToTarget();\n    }\n\n    \/** \u5feb\u901f\u67e5\u8a62\uff1a0 \u5948\u79d2\u7121\u9396\u8b80\u53d6\u5feb\u7167 *\/\n    public boolean isConnected() { return isConnected.get(); }\n\n    \/** \u4e0a\u50b3\u901a\u884c\u6293\u62cd\uff1a\u76f4\u63a5\u4e1f byte \u9663\u5217\u6392\u968a *\/\n    public void sendPassEvent(byte&#x5B;] protobufBytes) {\n        workerHandler.obtainMessage(MSG_SEND_EVENT, protobufBytes).sendToTarget();\n    }\n\n    private void handleConnect(String url) {\n        webSocketClient = new WebSocketClient(URI.create(url)) {\n            @Override\n            public void onOpen(ServerHandshake handshakedata) {\n                isConnected.set(true);\n                workerHandler.sendEmptyMessageDelayed(MSG_HEARTBEAT, 15000);\n            }\n            @Override\n            public void onClose(int code, String reason, boolean remote) {\n                isConnected.set(false);\n            }\n        };\n        webSocketClient.connect();\n    }\n\n    private void handleSendEvent(byte&#x5B;] data) {\n        if (isConnected.get() &amp;amp;&amp;amp; webSocketClient != null) webSocketClient.send(data);\n    }\n\n    private void handleHeartbeat() {\n        if (isConnected.get() &amp;amp;&amp;amp; webSocketClient != null) {\n            webSocketClient.send(ProtobufHelper.buildHeartbeatPacket());\n            workerHandler.sendEmptyMessageDelayed(MSG_HEARTBEAT, 15000);\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">2. \u65b7\u7db2\u5f8c\u7684\u5206\u6279\u88dc\u50b3\u6a5f\u5236\uff08LIMIT 20\uff09<\/h3>\n\n\n\n<p>\u82e5\u65b7\u7db2 3 \u5929\u7d2f\u7a4d\u6578\u5343\u7b46\u6253\u5361\uff0c\u7db2\u8def\u6062\u5fa9\u6642\u8a2d\u5099\u6bcf\u6b21\u50c5\u4e0a\u50b3 20 \u7b46\uff0c\u7b49\u4f3a\u670d\u5668\u56de\u50b3\u78ba\u8a8d\uff08ACK\uff09\u5beb\u5165\u6210\u529f\u5f8c\u624d\u7e7c\u7e8c\u6488\u4e0b\u4e00\u6279\uff0c\u5e73\u7a69\u6d88\u5316\u6b77\u53f2\u8cc7\u6599\uff0c\u9632\u8a18\u61b6\u9ad4\u7206\u6389\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u91cd\u9023\u96a8\u6a5f\u5ef6\u9072\uff08Jitter\uff09\u9632\u9023\u7dda\u98a8\u66b4<\/h3>\n\n\n\n<p>\u4f3a\u670d\u5668\u91cd\u555f\u6642\uff0c\u63a1\u7528\u300c\u6307\u6578\u9000\u907f \uff0b \u96a8\u6a5f\u52a0\u6e1b 500ms\u300d\uff0c\u5fb9\u5e95\u932f\u958b\u6578\u767e\u53f0\u8a2d\u5099\u7684\u91cd\u9023\u8acb\u6c42\uff0c\u907f\u514d\u77ac\u9593\u6253\u57ae\u4f3a\u670d\u5668\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><\/h2>\n\n\n\n<ul>\n<li><strong>WebSocket \u8ca0\u8cac\u300c\u5feb\u8207\u5373\u6642\u300d<\/strong>\uff1a\u7a7f\u900f\u5167\u7db2\uff0c\u5c08\u6ce8\u65bc 0.1 \u79d2\u5373\u6642\u958b\u9580\u3001\u5237\u81c9\u56de\u5831\u8207 Protobuf \u4f4e\u5ef6\u9072\u50b3\u8f38\uff1b<\/li>\n\n\n\n<li><strong>RESTful API \u8ca0\u8cac\u300c\u7a69\u8207\u901a\u7528\u300d<\/strong>\uff1a\u8655\u7406\u7b2c\u4e09\u65b9 HR \u5c0d\u63a5\u300150MB \u97cc\u9ad4\u5347\u7d1a\uff0c\u9694\u96e2\u5927\u6a94\u6848\u9632\u79a6\u968a\u982d\u963b\u585e\uff1b<\/li>\n\n\n\n<li><strong>\u908a\u7de3\u7aef\u4ee5 HandlerThread \u8207\u5206\u6279\u6a5f\u5236\u7576\u9632\u7dda<\/strong>\uff1a\u80cc\u666f\u55ae\u57f7\u884c\u7dd2\u6392\u968a\u5b88\u8b77 UI\uff0c\u5206\u6279\u88dc\u50b3\u8207 Jitter \u62b5\u79a6\u65b7\u7db2\u885d\u64ca\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u53c3\u8003\u6587\u737b\u8207\u51fa\u8655\uff08References\uff09<\/h3>\n\n\n\n<ol>\n<li><strong>gRPC \u5b98\u65b9\u5718\u968a\u67b6\u69cb\u6587\u4ef6<\/strong>\uff1agRPC-Web Official Documentation &amp; Specification (GitHub: <code>grpc\/grpc-web<\/code>, <em>State of gRPC in the Browser<\/em>)<\/li>\n\n\n\n<li><strong>WHATWG Fetch Living Standard<\/strong>\uff1aFetch API Specification &#8211; Section on HTTP\/2 Framing and Trailer Header Limitations in Browsers<\/li>\n\n\n\n<li><strong>IETF RFC 6455<\/strong>\uff1a<em>The WebSocket Protocol<\/em> &#8211; Protocol Upgrade &amp; Multiplexing Specifications<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u9762\u5e7e\u7bc7\u6211\u5011\u628a\u9ad8\u901a\u9a4d\u9f8d QM215\uff084 \u9846 A53\u30012GB RAM\uff09\u7684\u7cfb\u7d71\u7626\u8eab\u8207\u76f8\u6a5f\u96f6\u62f7\u8c9d\u69a8\u5230\u4e86\u6975\u81f4\u3002\u4f46\u7576\u9580\u7981\u6a5f\u639b\u4e0a\u5de5\u5ee0\u5927\u9580\u6642\uff0c\u73fe\u5834\u7684\u7db2\u8def\u6bd4\u6676\u7247\u66f4\u6158\uff1a\u8a2d\u5099\u8eb2\u5728\u4f01\u696d\u5167\u7db2\u6df1\u8655\uff08192.168.1.X \u7121\u516c\u7db2 IP\uff09\u3001\u7db2\u8def\u7dda\u96a8\u6642\u88ab\u62d4\u3001DNS \u52d5\u8f12\u5361\u6b7b 30 \u5728\u908a\u7de3 IoT \u7cfb\u7d71\u4e2d\uff0cWebSocket \u8207 RESTful API \u5230\u5e95\u8a72\u5982\u4f55\u7cbe\u6e96\u5206\u5de5\uff0c\u505a\u5230\u300c0.1 \u79d2\u5373\u6642\u958b\u9580\u3001\u96f6\u8a18\u61b6\u9ad4\u8ca0\u64d4\u3001\u65b7\u7db2 3 \u5929\u4e5f\u80fd\u7a69\u5065\u91cd\u9023\u300d\uff01<\/p>\n","protected":false},"author":1,"featured_media":1011,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,80],"tags":[],"_links":{"self":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1010"}],"collection":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1010"}],"version-history":[{"count":2,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1010\/revisions"}],"predecessor-version":[{"id":1014,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1010\/revisions\/1014"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/media\/1011"}],"wp:attachment":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}