[{"data":1,"prerenderedAt":21652},["ShallowReactive",2],{"wiki-page-\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0300-chuan-kou-tong-xin":3,"wiki-doc-items-2023-10-05-cplusplus-jiao-xue":21094,"wiki:author-members":21640},{"id":4,"title":5,"authors":6,"body":8,"chapterDepth":133,"chapterOrder":21082,"date":21083,"description":28,"docKey":21084,"docRoot":21085,"docTitle":21086,"extension":21087,"isWikiDoc":251,"isWikiIndex":21088,"meta":21089,"navigation":251,"path":21090,"seo":21091,"stem":21092,"wikiDepth":73,"__hash__":21093},"wiki\u002Fwiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0300-串口通信.md","串口通信教学",[7],"董佳辉",{"type":9,"value":10,"toc":20942},"minimark",[11,18,21,32,39,42,47,54,59,62,88,91,107,110,113,145,148,154,157,163,174,176,184,187,193,199,205,208,921,928,931,934,958,961,974,977,980,983,986,992,998,1001,1006,1011,1014,1017,1024,1027,1034,1037,1040,1049,1061,1070,1073,1079,1082,1088,1091,1094,1096,1103,1106,1111,1117,1123,1133,1139,1142,1145,1893,1898,1901,1903,1927,1930,1936,1939,1942,1945,1951,1956,1959,1962,1979,1984,1989,1992,1995,2000,2003,2046,2049,2071,2074,2077,2091,2094,2099,2102,2105,2111,2114,2120,2123,2126,2129,2135,2138,2158,2161,2201,2204,2210,2213,2219,2222,2225,2241,2249,2252,2255,2275,2277,2297,2300,2306,2309,2315,2318,2358,2364,2367,2373,2382,2385,2388,2394,2397,2400,2406,2409,2415,2418,2420,2427,2430,2470,2473,2489,2492,2498,2501,2507,2510,2550,2553,2565,2568,2570,2576,2579,2585,2588,2591,2597,2600,2606,2612,2614,2621,2624,2629,2632,2637,2640,2646,2649,2655,2658,2661,2701,2704,2710,2712,2719,2722,2724,2727,2732,2734,2736,2744,2747,2753,2761,2764,2767,2813,2815,2820,2823,2826,2832,2835,2841,2843,2849,2852,2872,2875,2881,2884,2887,2893,2896,2905,2908,2920,2923,2925,2931,2937,2955,2958,2964,2967,2973,2976,2979,2981,2987,2990,3045,3048,3057,3060,3078,3080,3086,3094,3096,3099,3115,3118,3121,3127,3130,3137,3139,3145,3148,3163,3169,3178,3180,3183,3217,3219,3225,3228,3239,3241,3248,3266,3269,3275,3278,3284,3287,3304,3306,3311,3313,3386,3389,3394,3400,3402,3408,3411,3417,3422,3428,3430,3450,3452,3457,3459,3465,3467,3532,3535,3546,3549,3552,3558,3561,3563,3569,3571,3581,3583,3588,3590,3595,3597,3667,3670,3676,3681,3687,3689,3694,3697,3703,3705,3724,3726,3731,3733,3739,3741,3801,3804,3810,3813,3816,3822,3825,3831,3834,3836,3847,3849,3854,3856,3860,3929,3932,3938,3944,3946,3958,3961,3983,3986,3994,3997,4000,4033,4036,4048,4051,4054,4060,4063,4066,4071,4074,4076,4117,4120,4126,4129,4147,4150,4156,4159,4165,4173,4176,4218,4221,4253,4255,4259,4262,4268,4270,4276,4279,4298,4300,4306,4309,4319,4322,4324,4330,4333,4352,4355,4361,4364,4374,4376,4390,4392,4399,4402,4405,4423,4426,4429,4449,4454,4460,4465,4468,4474,4477,5284,5287,5289,5313,5315,5320,5323,5333,5335,5338,5341,5347,5349,5354,5357,5363,5366,5369,5388,5391,5394,5400,5403,5415,5417,5420,5423,5441,5444,5450,5453,5471,5473,5479,5482,5494,5497,5509,5512,5526,5529,5531,5538,5541,5586,5589,5592,5616,5619,5622,5638,5641,5644,5685,5687,5693,5695,5701,5704,5725,5728,5770,5779,5782,5788,5791,5797,5800,5806,5809,5818,5821,5824,5922,5925,5937,5940,5942,5948,5950,5957,5999,6002,6007,6010,6013,6019,6021,6028,6030,6037,6040,6043,6061,6064,6067,6087,6090,6096,6102,6105,6108,6113,6115,6118,6121,6127,6130,7002,7005,7007,7031,7033,7036,7042,7045,7057,7060,7063,7077,7080,7083,7089,7092,7111,7114,7116,7122,7124,7127,7130,7148,7151,7157,7160,7178,7180,7186,7189,7209,7211,7252,7254,7259,7261,7266,7269,7275,7278,7284,7287,7299,7302,7304,7312,7315,7346,7349,7357,7360,7363,7411,7414,7442,7445,7459,7462,7464,7468,7470,7490,7493,7504,7507,7509,7515,7518,7521,7529,7532,7537,7539,7545,7586,7588,7593,7596,7599,7611,7614,7617,7630,7632,7640,7642,7646,7649,7652,7670,7673,7676,7727,7730,7741,7744,7747,7753,7756,7762,7765,7771,7774,9008,9011,9014,9038,9040,9050,9053,9056,9058,9064,9069,9072,9078,9083,9091,9094,9116,9119,9132,9135,9141,9143,9165,9168,9174,9176,9189,9192,9198,9200,9205,9208,9210,9222,9225,9231,9233,9237,9240,9261,9264,9269,9271,9277,9280,9286,9289,9299,9301,9306,9309,9312,9318,9320,9324,9327,9332,9335,9347,9350,9353,9366,9369,9374,9376,9382,9384,9418,9421,9427,9430,9436,9438,9442,9445,9524,9526,9532,9535,9556,9559,9562,9568,9570,9582,9585,9588,9590,9594,9597,9603,9606,9612,9615,9621,9624,9629,9631,9646,9648,9652,9655,9658,9676,9679,9682,9688,9691,9697,9700,9725,9728,9731,9741,9744,9756,9759,9765,9768,10725,10728,10730,10754,10757,10760,10766,10769,10808,10811,10814,10817,10823,10828,10833,10836,10839,10849,10852,10862,10865,10867,10879,10882,10884,10888,10891,10915,10918,10928,10931,10937,10940,10946,10949,10955,10958,10964,10967,10977,10980,10983,11018,11021,11023,11029,11031,11040,11042,11073,11076,11082,11085,11094,11097,11103,11106,11109,11111,11153,11156,11162,11165,11179,11182,11259,11262,11268,11271,11277,11280,11282,11289,11292,11313,11316,11322,11325,11335,11338,11373,11376,11384,11387,11390,11400,11403,11443,11446,11460,11462,11464,11470,11473,11479,11482,11485,11491,11493,11499,11501,11511,11514,11516,11522,11525,11531,11534,11542,11545,11551,11553,11559,11561,11567,11569,11619,11621,11635,11637,11643,11652,11654,11660,11663,11668,11671,11697,11699,11703,11706,11712,11715,11721,11723,11729,11731,11736,11738,11742,11745,11748,11754,11757,11760,11766,11769,11775,11778,11784,11787,11790,13302,13305,13307,13331,13333,13338,13341,13351,13354,13360,13375,13377,13382,13385,13390,13395,13398,13401,13422,13425,13435,13438,13444,13446,13449,13502,13505,13511,13513,13519,13522,13525,13531,13534,13536,13543,13546,13561,13564,13573,13576,13588,13591,13597,13600,13603,13609,13612,13625,13628,13631,13643,13646,13655,13657,13660,13663,13669,13672,13678,13680,13685,13687,13691,13694,13697,13700,13712,13715,13718,13724,13727,13733,13736,13742,13745,13751,13754,13759,13762,16137,16140,16142,16166,16168,16178,16181,16221,16224,16227,16241,16246,16249,16252,16258,16261,16267,16270,16276,16279,16285,16287,16294,16297,16303,16306,16308,16315,16318,16321,16340,16343,16354,16357,16369,16372,16378,16381,16389,16392,16398,16400,16410,16413,16425,16428,16467,16470,16505,16508,16514,16517,16520,16529,16532,16537,16539,16545,16548,16551,16559,16562,16580,16583,16596,16599,16611,16614,16621,16627,16630,16633,16644,16647,16649,16655,16657,16663,16666,16674,16677,16682,16684,16690,16692,16713,16716,16771,16773,16779,16781,16787,16789,16800,16803,16809,16811,16818,16821,16849,16852,16892,16895,16901,16904,16913,16915,16921,16924,16946,16949,16955,16958,16971,16974,16977,16985,16988,16994,16997,17005,17008,17013,17015,17026,17029,17068,17070,17083,17086,17089,17100,17103,17109,17112,17114,17127,17129,17137,17140,17146,17149,17155,17158,17171,17174,17177,17183,17185,17189,17191,17197,17199,17205,17207,17213,17216,17219,17229,17232,17234,17245,17247,17258,17261,17264,17267,17273,17276,17288,17290,17296,17299,17302,17310,17313,17319,17321,17327,17330,17332,17338,17341,17344,17352,17355,17358,17366,17369,19757,19760,19762,19786,19789,19799,19802,19805,19819,19826,19829,19835,19838,19844,19847,19849,19869,19872,19878,19881,19883,19889,19892,19894,19897,19902,19908,19910,19916,19919,19927,19930,19932,19938,19941,19965,19968,19974,19977,19986,19989,19991,20019,20022,20049,20051,20057,20060,20065,20068,20074,20077,20089,20092,20098,20100,20106,20109,20115,20117,20123,20126,20129,20134,20137,20139,20144,20147,20150,20156,20159,20162,20168,20170,20176,20178,20184,20186,20196,20199,20227,20229,20239,20242,20271,20273,20278,20281,20284,20290,20293,20296,20302,20305,20313,20316,20322,20324,20330,20333,20335,20344,20347,20349,20359,20362,20370,20373,20397,20400,20403,20409,20412,20418,20421,20426,20429,20435,20438,20441,20447,20449,20453,20455,20461,20464,20474,20477,20479,20485,20487,20493,20496,20508,20511,20513,20519,20522,20528,20530,20546,20550,20553,20565,20568,20763,20766,20837,20891,20894,20908,20911,20932,20935,20938],[12,13,14],"blockquote",{},[15,16,17],"p",{},"串口是机器人里最常见的通信方式之一：上位机 ROS2 \u002F Linux 程序通过 USB-TTL、USB-CAN 转串口、CH340、CP2102、FT232 等设备和 STM32、ESP32、下位机控制板通信。",[15,19,20],{},"本节依旧遵循顺序：",[22,23,29],"pre",{"className":24,"code":26,"language":27,"meta":28},[25],"language-text","先写普通 main() 里的同步示例\n再写普通 main() 里的异步示例\n最后写类封装版本\n","text","",[30,31,26],"code",{"__ignoreMap":28},[15,33,34,35,38],{},"所有异步回调统一使用 ",[30,36,37],{},"std::bind","。",[40,41],"hr",{},[43,44,46],"h2",{"id":45},"linux-下准备虚拟串口测试环境","Linux 下准备虚拟串口测试环境",[15,48,49,50,53],{},"如果你手里没有真实 STM32，可以用 ",[30,51,52],{},"socat"," 创建一对虚拟串口。",[55,56,58],"h3",{"id":57},"安装-socat","安装 socat",[15,60,61],{},"Ubuntu \u002F Debian：",[22,63,67],{"className":64,"code":65,"language":66,"meta":28,"style":28},"language-bash shiki shiki-themes github-light github-dark","sudo apt install socat\n","bash",[30,68,69],{"__ignoreMap":28},[70,71,74,78,82,85],"span",{"class":72,"line":73},"line",1,[70,75,77],{"class":76},"sScJk","sudo",[70,79,81],{"class":80},"sZZnC"," apt",[70,83,84],{"class":80}," install",[70,86,87],{"class":80}," socat\n",[15,89,90],{},"Fedora：",[22,92,94],{"className":64,"code":93,"language":66,"meta":28,"style":28},"sudo dnf install socat\n",[30,95,96],{"__ignoreMap":28},[70,97,98,100,103,105],{"class":72,"line":73},[70,99,77],{"class":76},[70,101,102],{"class":80}," dnf",[70,104,84],{"class":80},[70,106,87],{"class":80},[55,108,109],{"id":109},"创建一对虚拟串口",[15,111,112],{},"新开一个终端，运行：",[22,114,116],{"className":64,"code":115,"language":66,"meta":28,"style":28},"socat -d -d \\\n  PTY,raw,echo=0,link=\u002Ftmp\u002FttyV0 \\\n  PTY,raw,echo=0,link=\u002Ftmp\u002FttyV1\n",[30,117,118,131,139],{"__ignoreMap":28},[70,119,120,122,126,128],{"class":72,"line":73},[70,121,52],{"class":76},[70,123,125],{"class":124},"sj4cs"," -d",[70,127,125],{"class":124},[70,129,130],{"class":124}," \\\n",[70,132,134,137],{"class":72,"line":133},2,[70,135,136],{"class":80},"  PTY,raw,echo=0,link=\u002Ftmp\u002FttyV0",[70,138,130],{"class":124},[70,140,142],{"class":72,"line":141},3,[70,143,144],{"class":80},"  PTY,raw,echo=0,link=\u002Ftmp\u002FttyV1\n",[15,146,147],{},"你会看到类似输出：",[22,149,152],{"className":150,"code":151,"language":27,"meta":28},[25],"2026\u002F05\u002F24 12:00:00 socat[12345] N PTY is \u002Fdev\u002Fpts\u002F3\n2026\u002F05\u002F24 12:00:00 socat[12345] N PTY is \u002Fdev\u002Fpts\u002F4\n2026\u002F05\u002F24 12:00:00 socat[12345] N starting data transfer loop with FDs [5,5] and [7,7]\n",[30,153,151],{"__ignoreMap":28},[15,155,156],{},"这表示：",[22,158,161],{"className":159,"code":160,"language":27,"meta":28},[25],"\u002Fdev\u002Fpts\u002F3 和 \u002Fdev\u002Fpts\u002F4 是一对互通的虚拟串口\n程序写 \u002Fdev\u002Fpts\u002F3，另一个终端读 \u002Fdev\u002Fpts\u002F4 就能看到\n程序读 \u002Fdev\u002Fpts\u002F3，另一个终端写 \u002Fdev\u002Fpts\u002F4 就能发给程序\n\n同时我也给了他们别名\n\u002Fdev\u002Fpts\u002F3 和 \u002Ftmp\u002FttyV0是同一个东西\n\u002Fdev\u002Fpts\u002F4 和 \u002Ftmp\u002FttyV1是同一个东西\n",[30,162,160],{"__ignoreMap":28},[15,164,165,166,169,170,173],{},"下面示例都假设程序使用 ",[30,167,168],{},"\u002Fdev\u002Fpts\u002F3","，另一个终端使用 ",[30,171,172],{},"\u002Fdev\u002Fpts\u002F4","。你要按自己终端实际输出修改。",[40,175],{},[43,177,179,180,183],{"id":178},"示例-1普通-main-里同步打开串口并发送一行","示例 1：普通 ",[30,181,182],{},"main()"," 里同步打开串口并发送一行",[55,185,186],{"id":186},"程序目标",[15,188,189,190,192],{},"程序打开串口 ",[30,191,168],{},"，设置波特率 115200，然后发送：",[22,194,197],{"className":195,"code":196,"language":27,"meta":28},[25],"hello serial\n",[30,198,196],{"__ignoreMap":28},[15,200,201,202,204],{},"另一个终端从 ",[30,203,172],{}," 读到这行数据。",[55,206,207],{"id":207},"完整代码",[22,209,213],{"className":210,"code":211,"language":212,"meta":28,"style":28},"language-cpp shiki shiki-themes github-light github-dark","#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Cprint>\n#include \u003Cstring>\n\nint main(int argc, char* argv[])\n{\n    \u002F\u002F 程序从 main 函数开始执行，argc\u002Fargv 用来接收命令行参数。\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    \u002F\u002F io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n    boost::asio::io_context io;\n    \u002F\u002F serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial(io);\n    boost::system::error_code ec;\n\n    std::println(\"main：准备打开串口 {}\", port_name);\n\n    serial.open(port_name, ec);\n    if (ec)\n    {\n        std::println(\"打开串口失败：{}\", ec.message());\n        return 1;\n    }\n\n    serial.set_option(boost::asio::serial_port_base::baud_rate(115200));\n    serial.set_option(boost::asio::serial_port_base::character_size(8));\n    serial.set_option(boost::asio::serial_port_base::parity(\n        boost::asio::serial_port_base::parity::none));\n    serial.set_option(boost::asio::serial_port_base::stop_bits(\n        boost::asio::serial_port_base::stop_bits::one));\n    serial.set_option(boost::asio::serial_port_base::flow_control(\n        boost::asio::serial_port_base::flow_control::none));\n\n    std::string msg = \"hello serial\\n\";\n\n    \u002F\u002F 把缓冲区中的数据写入连接。\n    std::size_t n = boost::asio::write(serial, boost::asio::buffer(msg), ec);\n    if (ec)\n    {\n        std::println(\"发送失败：{}\", ec.message());\n        return 1;\n    }\n\n    std::println(\"main：发送成功，字节数 = {}\", n);\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n","cpp",[30,214,215,224,231,238,246,253,284,290,297,315,320,338,344,361,367,372,378,393,399,417,430,435,453,458,470,478,483,507,518,523,528,563,594,621,642,668,688,714,733,738,759,764,770,814,821,826,846,855,860,865,882,899,904,915],{"__ignoreMap":28},[70,216,217,221],{"class":72,"line":73},[70,218,220],{"class":219},"szBVR","#include",[70,222,223],{"class":80}," \u003Cboost\u002Fasio.hpp>\n",[70,225,226,228],{"class":72,"line":133},[70,227,220],{"class":219},[70,229,230],{"class":80}," \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n",[70,232,233,235],{"class":72,"line":141},[70,234,220],{"class":219},[70,236,237],{"class":80}," \u003Cprint>\n",[70,239,241,243],{"class":72,"line":240},4,[70,242,220],{"class":219},[70,244,245],{"class":80}," \u003Cstring>\n",[70,247,249],{"class":72,"line":248},5,[70,250,252],{"emptyLinePlaceholder":251},true,"\n",[70,254,256,259,262,266,268,272,275,278,281],{"class":72,"line":255},6,[70,257,258],{"class":219},"int",[70,260,261],{"class":76}," main",[70,263,265],{"class":264},"sVt8B","(",[70,267,258],{"class":219},[70,269,271],{"class":270},"s4XuR"," argc",[70,273,274],{"class":264},", ",[70,276,277],{"class":219},"char*",[70,279,280],{"class":270}," argv",[70,282,283],{"class":264},"[])\n",[70,285,287],{"class":72,"line":286},7,[70,288,289],{"class":264},"{\n",[70,291,293],{"class":72,"line":292},8,[70,294,296],{"class":295},"sJ8bj","    \u002F\u002F 程序从 main 函数开始执行，argc\u002Fargv 用来接收命令行参数。\n",[70,298,300,303,306,309,312],{"class":72,"line":299},9,[70,301,302],{"class":76},"    std",[70,304,305],{"class":264},"::string port_name ",[70,307,308],{"class":219},"=",[70,310,311],{"class":80}," \"\u002Fdev\u002Fpts\u002F3\"",[70,313,314],{"class":264},";\n",[70,316,318],{"class":72,"line":317},10,[70,319,252],{"emptyLinePlaceholder":251},[70,321,323,326,329,332,335],{"class":72,"line":322},11,[70,324,325],{"class":219},"    if",[70,327,328],{"class":264}," (argc ",[70,330,331],{"class":219},">=",[70,333,334],{"class":124}," 2",[70,336,337],{"class":264},")\n",[70,339,341],{"class":72,"line":340},12,[70,342,343],{"class":264},"    {\n",[70,345,347,350,352,355,358],{"class":72,"line":346},13,[70,348,349],{"class":264},"        port_name ",[70,351,308],{"class":219},[70,353,354],{"class":264}," argv[",[70,356,357],{"class":124},"1",[70,359,360],{"class":264},"];\n",[70,362,364],{"class":72,"line":363},14,[70,365,366],{"class":264},"    }\n",[70,368,370],{"class":72,"line":369},15,[70,371,252],{"emptyLinePlaceholder":251},[70,373,375],{"class":72,"line":374},16,[70,376,377],{"class":295},"    \u002F\u002F io_context 是 Asio 的事件循环对象，异步任务需要靠它调度。\n",[70,379,381,384,387,390],{"class":72,"line":380},17,[70,382,383],{"class":76},"    boost",[70,385,386],{"class":264},"::",[70,388,389],{"class":76},"asio",[70,391,392],{"class":264},"::io_context io;\n",[70,394,396],{"class":72,"line":395},18,[70,397,398],{"class":295},"    \u002F\u002F serial_port 表示串口设备，后续读写都通过它完成。\n",[70,400,402,404,406,408,411,414],{"class":72,"line":401},19,[70,403,383],{"class":76},[70,405,386],{"class":264},[70,407,389],{"class":76},[70,409,410],{"class":264},"::serial_port ",[70,412,413],{"class":76},"serial",[70,415,416],{"class":264},"(io);\n",[70,418,420,422,424,427],{"class":72,"line":419},20,[70,421,383],{"class":76},[70,423,386],{"class":264},[70,425,426],{"class":76},"system",[70,428,429],{"class":264},"::error_code ec;\n",[70,431,433],{"class":72,"line":432},21,[70,434,252],{"emptyLinePlaceholder":251},[70,436,438,440,442,445,447,450],{"class":72,"line":437},22,[70,439,302],{"class":76},[70,441,386],{"class":264},[70,443,444],{"class":76},"println",[70,446,265],{"class":264},[70,448,449],{"class":80},"\"main：准备打开串口 {}\"",[70,451,452],{"class":264},", port_name);\n",[70,454,456],{"class":72,"line":455},23,[70,457,252],{"emptyLinePlaceholder":251},[70,459,461,464,467],{"class":72,"line":460},24,[70,462,463],{"class":264},"    serial.",[70,465,466],{"class":76},"open",[70,468,469],{"class":264},"(port_name, ec);\n",[70,471,473,475],{"class":72,"line":472},25,[70,474,325],{"class":219},[70,476,477],{"class":264}," (ec)\n",[70,479,481],{"class":72,"line":480},26,[70,482,343],{"class":264},[70,484,486,489,491,493,495,498,501,504],{"class":72,"line":485},27,[70,487,488],{"class":76},"        std",[70,490,386],{"class":264},[70,492,444],{"class":76},[70,494,265],{"class":264},[70,496,497],{"class":80},"\"打开串口失败：{}\"",[70,499,500],{"class":264},", ec.",[70,502,503],{"class":76},"message",[70,505,506],{"class":264},"());\n",[70,508,510,513,516],{"class":72,"line":509},28,[70,511,512],{"class":219},"        return",[70,514,515],{"class":124}," 1",[70,517,314],{"class":264},[70,519,521],{"class":72,"line":520},29,[70,522,366],{"class":264},[70,524,526],{"class":72,"line":525},30,[70,527,252],{"emptyLinePlaceholder":251},[70,529,531,533,536,538,541,543,545,547,550,552,555,557,560],{"class":72,"line":530},31,[70,532,463],{"class":264},[70,534,535],{"class":76},"set_option",[70,537,265],{"class":264},[70,539,540],{"class":76},"boost",[70,542,386],{"class":264},[70,544,389],{"class":76},[70,546,386],{"class":264},[70,548,549],{"class":76},"serial_port_base",[70,551,386],{"class":264},[70,553,554],{"class":76},"baud_rate",[70,556,265],{"class":264},[70,558,559],{"class":124},"115200",[70,561,562],{"class":264},"));\n",[70,564,566,568,570,572,574,576,578,580,582,584,587,589,592],{"class":72,"line":565},32,[70,567,463],{"class":264},[70,569,535],{"class":76},[70,571,265],{"class":264},[70,573,540],{"class":76},[70,575,386],{"class":264},[70,577,389],{"class":76},[70,579,386],{"class":264},[70,581,549],{"class":76},[70,583,386],{"class":264},[70,585,586],{"class":76},"character_size",[70,588,265],{"class":264},[70,590,591],{"class":124},"8",[70,593,562],{"class":264},[70,595,597,599,601,603,605,607,609,611,613,615,618],{"class":72,"line":596},33,[70,598,463],{"class":264},[70,600,535],{"class":76},[70,602,265],{"class":264},[70,604,540],{"class":76},[70,606,386],{"class":264},[70,608,389],{"class":76},[70,610,386],{"class":264},[70,612,549],{"class":76},[70,614,386],{"class":264},[70,616,617],{"class":76},"parity",[70,619,620],{"class":264},"(\n",[70,622,624,627,629,631,633,635,637,639],{"class":72,"line":623},34,[70,625,626],{"class":76},"        boost",[70,628,386],{"class":264},[70,630,389],{"class":76},[70,632,386],{"class":264},[70,634,549],{"class":76},[70,636,386],{"class":264},[70,638,617],{"class":76},[70,640,641],{"class":264},"::none));\n",[70,643,645,647,649,651,653,655,657,659,661,663,666],{"class":72,"line":644},35,[70,646,463],{"class":264},[70,648,535],{"class":76},[70,650,265],{"class":264},[70,652,540],{"class":76},[70,654,386],{"class":264},[70,656,389],{"class":76},[70,658,386],{"class":264},[70,660,549],{"class":76},[70,662,386],{"class":264},[70,664,665],{"class":76},"stop_bits",[70,667,620],{"class":264},[70,669,671,673,675,677,679,681,683,685],{"class":72,"line":670},36,[70,672,626],{"class":76},[70,674,386],{"class":264},[70,676,389],{"class":76},[70,678,386],{"class":264},[70,680,549],{"class":76},[70,682,386],{"class":264},[70,684,665],{"class":76},[70,686,687],{"class":264},"::one));\n",[70,689,691,693,695,697,699,701,703,705,707,709,712],{"class":72,"line":690},37,[70,692,463],{"class":264},[70,694,535],{"class":76},[70,696,265],{"class":264},[70,698,540],{"class":76},[70,700,386],{"class":264},[70,702,389],{"class":76},[70,704,386],{"class":264},[70,706,549],{"class":76},[70,708,386],{"class":264},[70,710,711],{"class":76},"flow_control",[70,713,620],{"class":264},[70,715,717,719,721,723,725,727,729,731],{"class":72,"line":716},38,[70,718,626],{"class":76},[70,720,386],{"class":264},[70,722,389],{"class":76},[70,724,386],{"class":264},[70,726,549],{"class":76},[70,728,386],{"class":264},[70,730,711],{"class":76},[70,732,641],{"class":264},[70,734,736],{"class":72,"line":735},39,[70,737,252],{"emptyLinePlaceholder":251},[70,739,741,743,746,748,751,754,757],{"class":72,"line":740},40,[70,742,302],{"class":76},[70,744,745],{"class":264},"::string msg ",[70,747,308],{"class":219},[70,749,750],{"class":80}," \"hello serial",[70,752,753],{"class":124},"\\n",[70,755,756],{"class":80},"\"",[70,758,314],{"class":264},[70,760,762],{"class":72,"line":761},41,[70,763,252],{"emptyLinePlaceholder":251},[70,765,767],{"class":72,"line":766},42,[70,768,769],{"class":295},"    \u002F\u002F 把缓冲区中的数据写入连接。\n",[70,771,773,775,777,780,783,785,788,790,792,794,797,800,802,804,806,808,811],{"class":72,"line":772},43,[70,774,302],{"class":76},[70,776,386],{"class":264},[70,778,779],{"class":219},"size_t",[70,781,782],{"class":264}," n ",[70,784,308],{"class":219},[70,786,787],{"class":76}," boost",[70,789,386],{"class":264},[70,791,389],{"class":76},[70,793,386],{"class":264},[70,795,796],{"class":76},"write",[70,798,799],{"class":264},"(serial, ",[70,801,540],{"class":76},[70,803,386],{"class":264},[70,805,389],{"class":76},[70,807,386],{"class":264},[70,809,810],{"class":76},"buffer",[70,812,813],{"class":264},"(msg), ec);\n",[70,815,817,819],{"class":72,"line":816},44,[70,818,325],{"class":219},[70,820,477],{"class":264},[70,822,824],{"class":72,"line":823},45,[70,825,343],{"class":264},[70,827,829,831,833,835,837,840,842,844],{"class":72,"line":828},46,[70,830,488],{"class":76},[70,832,386],{"class":264},[70,834,444],{"class":76},[70,836,265],{"class":264},[70,838,839],{"class":80},"\"发送失败：{}\"",[70,841,500],{"class":264},[70,843,503],{"class":76},[70,845,506],{"class":264},[70,847,849,851,853],{"class":72,"line":848},47,[70,850,512],{"class":219},[70,852,515],{"class":124},[70,854,314],{"class":264},[70,856,858],{"class":72,"line":857},48,[70,859,366],{"class":264},[70,861,863],{"class":72,"line":862},49,[70,864,252],{"emptyLinePlaceholder":251},[70,866,868,870,872,874,876,879],{"class":72,"line":867},50,[70,869,302],{"class":76},[70,871,386],{"class":264},[70,873,444],{"class":76},[70,875,265],{"class":264},[70,877,878],{"class":80},"\"main：发送成功，字节数 = {}\"",[70,880,881],{"class":264},", n);\n",[70,883,885,887,889,891,893,896],{"class":72,"line":884},51,[70,886,302],{"class":76},[70,888,386],{"class":264},[70,890,444],{"class":76},[70,892,265],{"class":264},[70,894,895],{"class":80},"\"main：程序结束\"",[70,897,898],{"class":264},");\n",[70,900,902],{"class":72,"line":901},52,[70,903,252],{"emptyLinePlaceholder":251},[70,905,907,910,913],{"class":72,"line":906},53,[70,908,909],{"class":219},"    return",[70,911,912],{"class":124}," 0",[70,914,314],{"class":264},[70,916,918],{"class":72,"line":917},54,[70,919,920],{"class":264},"}\n",[15,922,923,927],{},[924,925,926],"strong",{},"运行结果","：见下方“运行输出与时间顺序”；如果示例涉及定时器、线程、网络或外部设备，具体时间和顺序可能会随环境略有变化。",[55,929,930],{"id":930},"编译运行",[15,932,933],{},"终端 1：创建虚拟串口。",[22,935,936],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,937,938,948,954],{"__ignoreMap":28},[70,939,940,942,944,946],{"class":72,"line":73},[70,941,52],{"class":76},[70,943,125],{"class":124},[70,945,125],{"class":124},[70,947,130],{"class":124},[70,949,950,952],{"class":72,"line":133},[70,951,136],{"class":80},[70,953,130],{"class":124},[70,955,956],{"class":72,"line":141},[70,957,144],{"class":80},[15,959,960],{},"终端 2：监听另一端。",[22,962,964],{"className":64,"code":963,"language":66,"meta":28,"style":28},"cat \u002Fdev\u002Fpts\u002F4\n",[30,965,966],{"__ignoreMap":28},[70,967,968,971],{"class":72,"line":73},[70,969,970],{"class":76},"cat",[70,972,973],{"class":80}," \u002Fdev\u002Fpts\u002F4\n",[15,975,976],{},"终端 3：编译运行程序。",[15,978,979],{},"运行刚才写的那个cpp来发送数据。",[55,981,982],{"id":982},"运行输出与时间顺序",[15,984,985],{},"程序终端输出：",[22,987,990],{"className":988,"code":989,"language":27,"meta":28},[25],"main：准备打开串口 \u002Fdev\u002Fpts\u002F3\nmain：发送成功，字节数 = 13\nmain：程序结束\n",[30,991,989],{"__ignoreMap":28},[15,993,994],{},[995,996],"img",{"alt":28,"src":997},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789374774994-2c36ef1c.webp",[15,999,1000],{},"监听终端输出：",[22,1002,1004],{"className":1003,"code":196,"language":27,"meta":28},[25],[30,1005,196],{"__ignoreMap":28},[15,1007,1008],{},[995,1009],{"alt":28,"src":1010},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789374757000-430588a5.webp",[15,1012,1013],{},"这个示例基本没有明显延迟，发送完成后程序立刻结束。",[55,1015,1016],{"id":1016},"本示例需要注意的点",[15,1018,1019,1020,1023],{},"这是同步写串口。",[30,1021,1022],{},"boost::asio::write()"," 会阻塞，直到数据写完或发生错误。",[55,1025,1026],{"id":1026},"关键函数说明",[1028,1029,1031],"h4",{"id":1030},"serialopenport_name-ec",[30,1032,1033],{},"serial.open(port_name, ec)",[15,1035,1036],{},"作用：打开串口设备。",[15,1038,1039],{},"参数：",[22,1041,1043],{"className":210,"code":1042,"language":212,"meta":28,"style":28},"port_name\n",[30,1044,1045],{"__ignoreMap":28},[70,1046,1047],{"class":72,"line":73},[70,1048,1042],{"class":264},[15,1050,1051,1052,1055,1056,1055,1059,38],{},"例如 ",[30,1053,1054],{},"\u002Fdev\u002FttyUSB0","、",[30,1057,1058],{},"\u002Fdev\u002FttyACM0",[30,1060,168],{},[22,1062,1064],{"className":210,"code":1063,"language":212,"meta":28,"style":28},"ec\n",[30,1065,1066],{"__ignoreMap":28},[70,1067,1068],{"class":72,"line":73},[70,1069,1063],{"class":264},[15,1071,1072],{},"用于接收错误信息。这样写不会抛异常，更适合教程和机器人工程。",[1028,1074,1076],{"id":1075},"serialset_option",[30,1077,1078],{},"serial.set_option(...)",[15,1080,1081],{},"作用：设置串口参数，例如波特率、数据位、校验位、停止位、流控。",[1028,1083,1085],{"id":1084},"boostasiowriteserial-boostasiobuffermsg-ec",[30,1086,1087],{},"boost::asio::write(serial, boost::asio::buffer(msg), ec)",[15,1089,1090],{},"作用：同步写数据。(阻塞式发数据)",[15,1092,1093],{},"返回值：实际写入的字节数。",[40,1095],{},[43,1097,1099,1100,1102],{"id":1098},"示例-2普通-main-里同步读取串口数据","示例 2：普通 ",[30,1101,182],{}," 里同步读取串口数据",[55,1104,186],{"id":1105},"程序目标-1",[15,1107,189,1108,1110],{},[30,1109,168],{},"，设置波特率 115200，然后阻塞等待接收 11 个字节。",[15,1112,1113,1114,1116],{},"另一个终端向 ",[30,1115,172],{}," 发送：",[22,1118,1121],{"className":1119,"code":1120,"language":27,"meta":28},[25],"hello asio\n",[30,1122,1120],{"__ignoreMap":28},[15,1124,1125,1126,1129,1130,1132],{},"由于 ",[30,1127,1128],{},"echo"," 会自动在末尾添加换行符 ",[30,1131,753],{},"，实际发送的是：",[22,1134,1137],{"className":1135,"code":1136,"language":27,"meta":28},[25],"hello asio\\n\n",[30,1138,1136],{"__ignoreMap":28},[15,1140,1141],{},"一共 11 个字节。",[55,1143,207],{"id":1144},"完整代码-1",[22,1146,1148],{"className":210,"code":1147,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n\n#include \u003Carray>\n#include \u003Cprint>\n#include \u003Cstring>\n\nint main(int argc, char* argv[])\n{\n    \u002F\u002F 程序从 main 函数开始执行，argc\u002Fargv 用来接收命令行参数。\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    \u002F\u002F io_context 是 Asio 的 I\u002FO 上下文。\n    boost::asio::io_context io;\n\n    \u002F\u002F serial_port 表示串口设备，后续读写都通过它完成。\n    boost::asio::serial_port serial(io);\n\n    boost::system::error_code ec;\n\n    std::println(\"main：准备打开串口 {}\", port_name);\n\n    serial.open(port_name, ec);\n\n    if (ec)\n    {\n        std::println(\"打开串口失败：{}\", ec.message());\n        return 1;\n    }\n\n    serial.set_option(\n        boost::asio::serial_port_base::baud_rate(115200));\n\n    serial.set_option(\n        boost::asio::serial_port_base::character_size(8));\n\n    serial.set_option(\n        boost::asio::serial_port_base::parity(\n            boost::asio::serial_port_base::parity::none));\n\n    serial.set_option(\n        boost::asio::serial_port_base::stop_bits(\n            boost::asio::serial_port_base::stop_bits::one));\n\n    serial.set_option(\n        boost::asio::serial_port_base::flow_control(\n            boost::asio::serial_port_base::flow_control::none));\n\n    \u002F\u002F 创建一个 11 字节的接收缓冲区。\n    std::array\u003Cchar, 11> buffer{};\n\n    std::println(\"main：等待接收 11 个字节\");\n\n    \u002F\u002F 同步读取串口数据。\n    \u002F\u002F 会一直阻塞，直到整个 buffer 被填满或者发生错误。\n    std::size_t n =\n        boost::asio::read(\n            serial,\n            boost::asio::buffer(buffer),\n            ec);\n\n    if (ec)\n    {\n        std::println(\"读取失败：{}\", ec.message());\n        return 1;\n    }\n\n    \u002F\u002F 把实际读取到的 n 个字节转换成字符串。\n    std::string msg(buffer.data(), n);\n\n    std::println(\"main：读取成功，字节数 = {}\", n);\n    std::println(\"main：收到的数据 = {}\", msg);\n\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n",[30,1149,1150,1156,1162,1166,1173,1179,1185,1189,1209,1213,1217,1229,1233,1245,1249,1261,1265,1269,1274,1284,1288,1292,1306,1310,1320,1324,1338,1342,1350,1354,1360,1364,1382,1390,1394,1398,1406,1428,1432,1440,1462,1466,1474,1492,1511,1515,1523,1541,1559,1563,1571,1589,1607,1611,1616,1638,1643,1659,1664,1670,1676,1690,1706,1712,1728,1734,1739,1746,1751,1771,1780,1785,1790,1796,1816,1821,1837,1854,1859,1874,1879,1888],{"__ignoreMap":28},[70,1151,1152,1154],{"class":72,"line":73},[70,1153,220],{"class":219},[70,1155,223],{"class":80},[70,1157,1158,1160],{"class":72,"line":133},[70,1159,220],{"class":219},[70,1161,230],{"class":80},[70,1163,1164],{"class":72,"line":141},[70,1165,252],{"emptyLinePlaceholder":251},[70,1167,1168,1170],{"class":72,"line":240},[70,1169,220],{"class":219},[70,1171,1172],{"class":80}," \u003Carray>\n",[70,1174,1175,1177],{"class":72,"line":248},[70,1176,220],{"class":219},[70,1178,237],{"class":80},[70,1180,1181,1183],{"class":72,"line":255},[70,1182,220],{"class":219},[70,1184,245],{"class":80},[70,1186,1187],{"class":72,"line":286},[70,1188,252],{"emptyLinePlaceholder":251},[70,1190,1191,1193,1195,1197,1199,1201,1203,1205,1207],{"class":72,"line":292},[70,1192,258],{"class":219},[70,1194,261],{"class":76},[70,1196,265],{"class":264},[70,1198,258],{"class":219},[70,1200,271],{"class":270},[70,1202,274],{"class":264},[70,1204,277],{"class":219},[70,1206,280],{"class":270},[70,1208,283],{"class":264},[70,1210,1211],{"class":72,"line":299},[70,1212,289],{"class":264},[70,1214,1215],{"class":72,"line":317},[70,1216,296],{"class":295},[70,1218,1219,1221,1223,1225,1227],{"class":72,"line":322},[70,1220,302],{"class":76},[70,1222,305],{"class":264},[70,1224,308],{"class":219},[70,1226,311],{"class":80},[70,1228,314],{"class":264},[70,1230,1231],{"class":72,"line":340},[70,1232,252],{"emptyLinePlaceholder":251},[70,1234,1235,1237,1239,1241,1243],{"class":72,"line":346},[70,1236,325],{"class":219},[70,1238,328],{"class":264},[70,1240,331],{"class":219},[70,1242,334],{"class":124},[70,1244,337],{"class":264},[70,1246,1247],{"class":72,"line":363},[70,1248,343],{"class":264},[70,1250,1251,1253,1255,1257,1259],{"class":72,"line":369},[70,1252,349],{"class":264},[70,1254,308],{"class":219},[70,1256,354],{"class":264},[70,1258,357],{"class":124},[70,1260,360],{"class":264},[70,1262,1263],{"class":72,"line":374},[70,1264,366],{"class":264},[70,1266,1267],{"class":72,"line":380},[70,1268,252],{"emptyLinePlaceholder":251},[70,1270,1271],{"class":72,"line":395},[70,1272,1273],{"class":295},"    \u002F\u002F io_context 是 Asio 的 I\u002FO 上下文。\n",[70,1275,1276,1278,1280,1282],{"class":72,"line":401},[70,1277,383],{"class":76},[70,1279,386],{"class":264},[70,1281,389],{"class":76},[70,1283,392],{"class":264},[70,1285,1286],{"class":72,"line":419},[70,1287,252],{"emptyLinePlaceholder":251},[70,1289,1290],{"class":72,"line":432},[70,1291,398],{"class":295},[70,1293,1294,1296,1298,1300,1302,1304],{"class":72,"line":437},[70,1295,383],{"class":76},[70,1297,386],{"class":264},[70,1299,389],{"class":76},[70,1301,410],{"class":264},[70,1303,413],{"class":76},[70,1305,416],{"class":264},[70,1307,1308],{"class":72,"line":455},[70,1309,252],{"emptyLinePlaceholder":251},[70,1311,1312,1314,1316,1318],{"class":72,"line":460},[70,1313,383],{"class":76},[70,1315,386],{"class":264},[70,1317,426],{"class":76},[70,1319,429],{"class":264},[70,1321,1322],{"class":72,"line":472},[70,1323,252],{"emptyLinePlaceholder":251},[70,1325,1326,1328,1330,1332,1334,1336],{"class":72,"line":480},[70,1327,302],{"class":76},[70,1329,386],{"class":264},[70,1331,444],{"class":76},[70,1333,265],{"class":264},[70,1335,449],{"class":80},[70,1337,452],{"class":264},[70,1339,1340],{"class":72,"line":485},[70,1341,252],{"emptyLinePlaceholder":251},[70,1343,1344,1346,1348],{"class":72,"line":509},[70,1345,463],{"class":264},[70,1347,466],{"class":76},[70,1349,469],{"class":264},[70,1351,1352],{"class":72,"line":520},[70,1353,252],{"emptyLinePlaceholder":251},[70,1355,1356,1358],{"class":72,"line":525},[70,1357,325],{"class":219},[70,1359,477],{"class":264},[70,1361,1362],{"class":72,"line":530},[70,1363,343],{"class":264},[70,1365,1366,1368,1370,1372,1374,1376,1378,1380],{"class":72,"line":565},[70,1367,488],{"class":76},[70,1369,386],{"class":264},[70,1371,444],{"class":76},[70,1373,265],{"class":264},[70,1375,497],{"class":80},[70,1377,500],{"class":264},[70,1379,503],{"class":76},[70,1381,506],{"class":264},[70,1383,1384,1386,1388],{"class":72,"line":596},[70,1385,512],{"class":219},[70,1387,515],{"class":124},[70,1389,314],{"class":264},[70,1391,1392],{"class":72,"line":623},[70,1393,366],{"class":264},[70,1395,1396],{"class":72,"line":644},[70,1397,252],{"emptyLinePlaceholder":251},[70,1399,1400,1402,1404],{"class":72,"line":670},[70,1401,463],{"class":264},[70,1403,535],{"class":76},[70,1405,620],{"class":264},[70,1407,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426],{"class":72,"line":690},[70,1409,626],{"class":76},[70,1411,386],{"class":264},[70,1413,389],{"class":76},[70,1415,386],{"class":264},[70,1417,549],{"class":76},[70,1419,386],{"class":264},[70,1421,554],{"class":76},[70,1423,265],{"class":264},[70,1425,559],{"class":124},[70,1427,562],{"class":264},[70,1429,1430],{"class":72,"line":716},[70,1431,252],{"emptyLinePlaceholder":251},[70,1433,1434,1436,1438],{"class":72,"line":735},[70,1435,463],{"class":264},[70,1437,535],{"class":76},[70,1439,620],{"class":264},[70,1441,1442,1444,1446,1448,1450,1452,1454,1456,1458,1460],{"class":72,"line":740},[70,1443,626],{"class":76},[70,1445,386],{"class":264},[70,1447,389],{"class":76},[70,1449,386],{"class":264},[70,1451,549],{"class":76},[70,1453,386],{"class":264},[70,1455,586],{"class":76},[70,1457,265],{"class":264},[70,1459,591],{"class":124},[70,1461,562],{"class":264},[70,1463,1464],{"class":72,"line":761},[70,1465,252],{"emptyLinePlaceholder":251},[70,1467,1468,1470,1472],{"class":72,"line":766},[70,1469,463],{"class":264},[70,1471,535],{"class":76},[70,1473,620],{"class":264},[70,1475,1476,1478,1480,1482,1484,1486,1488,1490],{"class":72,"line":772},[70,1477,626],{"class":76},[70,1479,386],{"class":264},[70,1481,389],{"class":76},[70,1483,386],{"class":264},[70,1485,549],{"class":76},[70,1487,386],{"class":264},[70,1489,617],{"class":76},[70,1491,620],{"class":264},[70,1493,1494,1497,1499,1501,1503,1505,1507,1509],{"class":72,"line":816},[70,1495,1496],{"class":76},"            boost",[70,1498,386],{"class":264},[70,1500,389],{"class":76},[70,1502,386],{"class":264},[70,1504,549],{"class":76},[70,1506,386],{"class":264},[70,1508,617],{"class":76},[70,1510,641],{"class":264},[70,1512,1513],{"class":72,"line":823},[70,1514,252],{"emptyLinePlaceholder":251},[70,1516,1517,1519,1521],{"class":72,"line":828},[70,1518,463],{"class":264},[70,1520,535],{"class":76},[70,1522,620],{"class":264},[70,1524,1525,1527,1529,1531,1533,1535,1537,1539],{"class":72,"line":848},[70,1526,626],{"class":76},[70,1528,386],{"class":264},[70,1530,389],{"class":76},[70,1532,386],{"class":264},[70,1534,549],{"class":76},[70,1536,386],{"class":264},[70,1538,665],{"class":76},[70,1540,620],{"class":264},[70,1542,1543,1545,1547,1549,1551,1553,1555,1557],{"class":72,"line":857},[70,1544,1496],{"class":76},[70,1546,386],{"class":264},[70,1548,389],{"class":76},[70,1550,386],{"class":264},[70,1552,549],{"class":76},[70,1554,386],{"class":264},[70,1556,665],{"class":76},[70,1558,687],{"class":264},[70,1560,1561],{"class":72,"line":862},[70,1562,252],{"emptyLinePlaceholder":251},[70,1564,1565,1567,1569],{"class":72,"line":867},[70,1566,463],{"class":264},[70,1568,535],{"class":76},[70,1570,620],{"class":264},[70,1572,1573,1575,1577,1579,1581,1583,1585,1587],{"class":72,"line":884},[70,1574,626],{"class":76},[70,1576,386],{"class":264},[70,1578,389],{"class":76},[70,1580,386],{"class":264},[70,1582,549],{"class":76},[70,1584,386],{"class":264},[70,1586,711],{"class":76},[70,1588,620],{"class":264},[70,1590,1591,1593,1595,1597,1599,1601,1603,1605],{"class":72,"line":901},[70,1592,1496],{"class":76},[70,1594,386],{"class":264},[70,1596,389],{"class":76},[70,1598,386],{"class":264},[70,1600,549],{"class":76},[70,1602,386],{"class":264},[70,1604,711],{"class":76},[70,1606,641],{"class":264},[70,1608,1609],{"class":72,"line":906},[70,1610,252],{"emptyLinePlaceholder":251},[70,1612,1613],{"class":72,"line":917},[70,1614,1615],{"class":295},"    \u002F\u002F 创建一个 11 字节的接收缓冲区。\n",[70,1617,1619,1621,1624,1627,1629,1632,1635],{"class":72,"line":1618},55,[70,1620,302],{"class":76},[70,1622,1623],{"class":264},"::array",[70,1625,1626],{"class":219},"\u003Cchar",[70,1628,274],{"class":264},[70,1630,1631],{"class":124},"11",[70,1633,1634],{"class":219},">",[70,1636,1637],{"class":264}," buffer{};\n",[70,1639,1641],{"class":72,"line":1640},56,[70,1642,252],{"emptyLinePlaceholder":251},[70,1644,1646,1648,1650,1652,1654,1657],{"class":72,"line":1645},57,[70,1647,302],{"class":76},[70,1649,386],{"class":264},[70,1651,444],{"class":76},[70,1653,265],{"class":264},[70,1655,1656],{"class":80},"\"main：等待接收 11 个字节\"",[70,1658,898],{"class":264},[70,1660,1662],{"class":72,"line":1661},58,[70,1663,252],{"emptyLinePlaceholder":251},[70,1665,1667],{"class":72,"line":1666},59,[70,1668,1669],{"class":295},"    \u002F\u002F 同步读取串口数据。\n",[70,1671,1673],{"class":72,"line":1672},60,[70,1674,1675],{"class":295},"    \u002F\u002F 会一直阻塞，直到整个 buffer 被填满或者发生错误。\n",[70,1677,1679,1681,1683,1685,1687],{"class":72,"line":1678},61,[70,1680,302],{"class":76},[70,1682,386],{"class":264},[70,1684,779],{"class":219},[70,1686,782],{"class":264},[70,1688,1689],{"class":219},"=\n",[70,1691,1693,1695,1697,1699,1701,1704],{"class":72,"line":1692},62,[70,1694,626],{"class":76},[70,1696,386],{"class":264},[70,1698,389],{"class":76},[70,1700,386],{"class":264},[70,1702,1703],{"class":76},"read",[70,1705,620],{"class":264},[70,1707,1709],{"class":72,"line":1708},63,[70,1710,1711],{"class":264},"            serial,\n",[70,1713,1715,1717,1719,1721,1723,1725],{"class":72,"line":1714},64,[70,1716,1496],{"class":76},[70,1718,386],{"class":264},[70,1720,389],{"class":76},[70,1722,386],{"class":264},[70,1724,810],{"class":76},[70,1726,1727],{"class":264},"(buffer),\n",[70,1729,1731],{"class":72,"line":1730},65,[70,1732,1733],{"class":264},"            ec);\n",[70,1735,1737],{"class":72,"line":1736},66,[70,1738,252],{"emptyLinePlaceholder":251},[70,1740,1742,1744],{"class":72,"line":1741},67,[70,1743,325],{"class":219},[70,1745,477],{"class":264},[70,1747,1749],{"class":72,"line":1748},68,[70,1750,343],{"class":264},[70,1752,1754,1756,1758,1760,1762,1765,1767,1769],{"class":72,"line":1753},69,[70,1755,488],{"class":76},[70,1757,386],{"class":264},[70,1759,444],{"class":76},[70,1761,265],{"class":264},[70,1763,1764],{"class":80},"\"读取失败：{}\"",[70,1766,500],{"class":264},[70,1768,503],{"class":76},[70,1770,506],{"class":264},[70,1772,1774,1776,1778],{"class":72,"line":1773},70,[70,1775,512],{"class":219},[70,1777,515],{"class":124},[70,1779,314],{"class":264},[70,1781,1783],{"class":72,"line":1782},71,[70,1784,366],{"class":264},[70,1786,1788],{"class":72,"line":1787},72,[70,1789,252],{"emptyLinePlaceholder":251},[70,1791,1793],{"class":72,"line":1792},73,[70,1794,1795],{"class":295},"    \u002F\u002F 把实际读取到的 n 个字节转换成字符串。\n",[70,1797,1799,1801,1804,1807,1810,1813],{"class":72,"line":1798},74,[70,1800,302],{"class":76},[70,1802,1803],{"class":264},"::string ",[70,1805,1806],{"class":76},"msg",[70,1808,1809],{"class":264},"(buffer.",[70,1811,1812],{"class":76},"data",[70,1814,1815],{"class":264},"(), n);\n",[70,1817,1819],{"class":72,"line":1818},75,[70,1820,252],{"emptyLinePlaceholder":251},[70,1822,1824,1826,1828,1830,1832,1835],{"class":72,"line":1823},76,[70,1825,302],{"class":76},[70,1827,386],{"class":264},[70,1829,444],{"class":76},[70,1831,265],{"class":264},[70,1833,1834],{"class":80},"\"main：读取成功，字节数 = {}\"",[70,1836,881],{"class":264},[70,1838,1840,1842,1844,1846,1848,1851],{"class":72,"line":1839},77,[70,1841,302],{"class":76},[70,1843,386],{"class":264},[70,1845,444],{"class":76},[70,1847,265],{"class":264},[70,1849,1850],{"class":80},"\"main：收到的数据 = {}\"",[70,1852,1853],{"class":264},", msg);\n",[70,1855,1857],{"class":72,"line":1856},78,[70,1858,252],{"emptyLinePlaceholder":251},[70,1860,1862,1864,1866,1868,1870,1872],{"class":72,"line":1861},79,[70,1863,302],{"class":76},[70,1865,386],{"class":264},[70,1867,444],{"class":76},[70,1869,265],{"class":264},[70,1871,895],{"class":80},[70,1873,898],{"class":264},[70,1875,1877],{"class":72,"line":1876},80,[70,1878,252],{"emptyLinePlaceholder":251},[70,1880,1882,1884,1886],{"class":72,"line":1881},81,[70,1883,909],{"class":219},[70,1885,912],{"class":124},[70,1887,314],{"class":264},[70,1889,1891],{"class":72,"line":1890},82,[70,1892,920],{"class":264},[15,1894,1895,1897],{},[924,1896,926],{},"：见下方“运行输出与时间顺序”；如果示例涉及串口、线程、网络或外部设备，具体时间和顺序可能会随环境略有变化。",[55,1899,930],{"id":1900},"编译运行-1",[15,1902,933],{},[22,1904,1905],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,1906,1907,1917,1923],{"__ignoreMap":28},[70,1908,1909,1911,1913,1915],{"class":72,"line":73},[70,1910,52],{"class":76},[70,1912,125],{"class":124},[70,1914,125],{"class":124},[70,1916,130],{"class":124},[70,1918,1919,1921],{"class":72,"line":133},[70,1920,136],{"class":80},[70,1922,130],{"class":124},[70,1924,1925],{"class":72,"line":141},[70,1926,144],{"class":80},[15,1928,1929],{},"假设得到：",[22,1931,1934],{"className":1932,"code":1933,"language":27,"meta":28},[25],"\u002Fdev\u002Fpts\u002F3\n\u002Fdev\u002Fpts\u002F4\n",[30,1935,1933],{"__ignoreMap":28},[15,1937,1938],{},"终端 2：编译运行程序。",[15,1940,1941],{},"编译运行程序后，",[15,1943,1944],{},"程序此时输出：",[22,1946,1949],{"className":1947,"code":1948,"language":27,"meta":28},[25],"main：准备打开串口 \u002Fdev\u002Fpts\u002F3\nmain：等待接收 11 个字节\n",[30,1950,1948],{"__ignoreMap":28},[15,1952,1953],{},[995,1954],{"alt":28,"src":1955},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789377580436-ef3668ee.webp",[15,1957,1958],{},"然后程序会阻塞等待串口数据。",[15,1960,1961],{},"终端 3：向另一端发送数据。",[22,1963,1965],{"className":64,"code":1964,"language":66,"meta":28,"style":28},"echo \"hello asio\" > \u002Fdev\u002Fpts\u002F4\n",[30,1966,1967],{"__ignoreMap":28},[70,1968,1969,1971,1974,1977],{"class":72,"line":73},[70,1970,1128],{"class":124},[70,1972,1973],{"class":80}," \"hello asio\"",[70,1975,1976],{"class":219}," >",[70,1978,973],{"class":80},[15,1980,1981],{},[995,1982],{"alt":28,"src":1983},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789377561915-e9063cc0.webp",[15,1985,1986],{},[995,1987],{"alt":28,"src":1988},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789377602353-447bf95e.webp",[55,1990,982],{"id":1991},"运行输出与时间顺序-1",[15,1993,1994],{},"程序启动后输出：",[22,1996,1998],{"className":1997,"code":1948,"language":27,"meta":28},[25],[30,1999,1948],{"__ignoreMap":28},[15,2001,2002],{},"随后程序执行：",[22,2004,2006],{"className":210,"code":2005,"language":212,"meta":28,"style":28},"boost::asio::read(\n    serial,\n    boost::asio::buffer(buffer),\n    ec);\n",[30,2007,2008,2022,2027,2041],{"__ignoreMap":28},[70,2009,2010,2012,2014,2016,2018,2020],{"class":72,"line":73},[70,2011,540],{"class":76},[70,2013,386],{"class":264},[70,2015,389],{"class":76},[70,2017,386],{"class":264},[70,2019,1703],{"class":76},[70,2021,620],{"class":264},[70,2023,2024],{"class":72,"line":133},[70,2025,2026],{"class":264},"    serial,\n",[70,2028,2029,2031,2033,2035,2037,2039],{"class":72,"line":141},[70,2030,383],{"class":76},[70,2032,386],{"class":264},[70,2034,389],{"class":76},[70,2036,386],{"class":264},[70,2038,810],{"class":76},[70,2040,1727],{"class":264},[70,2042,2043],{"class":72,"line":240},[70,2044,2045],{"class":264},"    ec);\n",[15,2047,2048],{},"因为：",[22,2050,2052],{"className":210,"code":2051,"language":212,"meta":28,"style":28},"std::array\u003Cchar, 11> buffer{};\n",[30,2053,2054],{"__ignoreMap":28},[70,2055,2056,2059,2061,2063,2065,2067,2069],{"class":72,"line":73},[70,2057,2058],{"class":76},"std",[70,2060,1623],{"class":264},[70,2062,1626],{"class":219},[70,2064,274],{"class":264},[70,2066,1631],{"class":124},[70,2068,1634],{"class":219},[70,2070,1637],{"class":264},[15,2072,2073],{},"buffer 的大小是 11 字节，所以程序会一直阻塞，直到接收到 11 个字节。",[15,2075,2076],{},"当另一个终端执行：",[22,2078,2079],{"className":64,"code":1964,"language":66,"meta":28,"style":28},[30,2080,2081],{"__ignoreMap":28},[70,2082,2083,2085,2087,2089],{"class":72,"line":73},[70,2084,1128],{"class":124},[70,2086,1973],{"class":80},[70,2088,1976],{"class":219},[70,2090,973],{"class":80},[15,2092,2093],{},"实际发送的数据是：",[22,2095,2097],{"className":2096,"code":1136,"language":27,"meta":28},[25],[30,2098,1136],{"__ignoreMap":28},[15,2100,2101],{},"正好 11 个字节。",[15,2103,2104],{},"程序随后继续输出：",[22,2106,2109],{"className":2107,"code":2108,"language":27,"meta":28},[25],"main：读取成功，字节数 = 11\nmain：收到的数据 = hello asio\n\nmain：程序结束\n",[30,2110,2108],{"__ignoreMap":28},[15,2112,2113],{},"这里看起来会多换一行，是因为收到的数据末尾本身包含：",[22,2115,2118],{"className":2116,"code":2117,"language":27,"meta":28},[25],"\\n\n",[30,2119,2117],{"__ignoreMap":28},[15,2121,2122],{},"这个示例的等待时间取决于你什么时候向串口发送数据。",[55,2124,1016],{"id":2125},"本示例需要注意的点-1",[15,2127,2128],{},"这是同步读串口。",[15,2130,2131,2134],{},[30,2132,2133],{},"boost::asio::read()"," 会阻塞当前线程，直到指定的 buffer 被填满或者发生错误。",[15,2136,2137],{},"本例中：",[22,2139,2140],{"className":210,"code":2051,"language":212,"meta":28,"style":28},[30,2141,2142],{"__ignoreMap":28},[70,2143,2144,2146,2148,2150,2152,2154,2156],{"class":72,"line":73},[70,2145,2058],{"class":76},[70,2147,1623],{"class":264},[70,2149,1626],{"class":219},[70,2151,274],{"class":264},[70,2153,1631],{"class":124},[70,2155,1634],{"class":219},[70,2157,1637],{"class":264},[15,2159,2160],{},"所以：",[22,2162,2163],{"className":210,"code":2005,"language":212,"meta":28,"style":28},[30,2164,2165,2179,2183,2197],{"__ignoreMap":28},[70,2166,2167,2169,2171,2173,2175,2177],{"class":72,"line":73},[70,2168,540],{"class":76},[70,2170,386],{"class":264},[70,2172,389],{"class":76},[70,2174,386],{"class":264},[70,2176,1703],{"class":76},[70,2178,620],{"class":264},[70,2180,2181],{"class":72,"line":133},[70,2182,2026],{"class":264},[70,2184,2185,2187,2189,2191,2193,2195],{"class":72,"line":141},[70,2186,383],{"class":76},[70,2188,386],{"class":264},[70,2190,389],{"class":76},[70,2192,386],{"class":264},[70,2194,810],{"class":76},[70,2196,1727],{"class":264},[70,2198,2199],{"class":72,"line":240},[70,2200,2045],{"class":264},[15,2202,2203],{},"表示：",[22,2205,2208],{"className":2206,"code":2207,"language":27,"meta":28},[25],"一直等待并读取数据\n↓\n累计收到 11 个字节\n↓\nread() 返回\n",[30,2209,2207],{"__ignoreMap":28},[15,2211,2212],{},"如果只发送：",[22,2214,2217],{"className":2215,"code":2216,"language":27,"meta":28},[25],"hello\n",[30,2218,2216],{"__ignoreMap":28},[15,2220,2221],{},"由于还没有达到 11 个字节，程序仍然会继续阻塞等待剩余数据。",[15,2223,2224],{},"因为这里使用的是同步读取，所以不需要：",[22,2226,2228],{"className":210,"code":2227,"language":212,"meta":28,"style":28},"io.run();\n",[30,2229,2230],{"__ignoreMap":28},[70,2231,2232,2235,2238],{"class":72,"line":73},[70,2233,2234],{"class":264},"io.",[70,2236,2237],{"class":76},"run",[70,2239,2240],{"class":264},"();\n",[55,2242,2244,2245,2248],{"id":2243},"如果实际收到的数据远远超过-11-个字节会不会把-array-撑爆","如果实际收到的数据远远超过 11 个字节，会不会把 ",[30,2246,2247],{},"array"," 撑爆？",[15,2250,2251],{},"不会。",[15,2253,2254],{},"例如本例的接收缓冲区只有：",[22,2256,2257],{"className":210,"code":2051,"language":212,"meta":28,"style":28},[30,2258,2259],{"__ignoreMap":28},[70,2260,2261,2263,2265,2267,2269,2271,2273],{"class":72,"line":73},[70,2262,2058],{"class":76},[70,2264,1623],{"class":264},[70,2266,1626],{"class":219},[70,2268,274],{"class":264},[70,2270,1631],{"class":124},[70,2272,1634],{"class":219},[70,2274,1637],{"class":264},[15,2276,2160],{},[22,2278,2280],{"className":210,"code":2279,"language":212,"meta":28,"style":28},"boost::asio::buffer(buffer)\n",[30,2281,2282],{"__ignoreMap":28},[70,2283,2284,2286,2288,2290,2292,2294],{"class":72,"line":73},[70,2285,540],{"class":76},[70,2287,386],{"class":264},[70,2289,389],{"class":76},[70,2291,386],{"class":264},[70,2293,810],{"class":76},[70,2295,2296],{"class":264},"(buffer)\n",[15,2298,2299],{},"告诉 Asio 的信息相当于：",[22,2301,2304],{"className":2302,"code":2303,"language":27,"meta":28},[25],"这块接收内存最多只有 11 字节\n",[30,2305,2303],{"__ignoreMap":28},[15,2307,2308],{},"因此，即使串口实际上已经收到了 100 个字节：",[22,2310,2313],{"className":2311,"code":2312,"language":27,"meta":28},[25],"0 1 2 3 4 5 6 7 8 9 10 11 12 ... 99\n",[30,2314,2312],{"__ignoreMap":28},[15,2316,2317],{},"这次：",[22,2319,2320],{"className":210,"code":2005,"language":212,"meta":28,"style":28},[30,2321,2322,2336,2340,2354],{"__ignoreMap":28},[70,2323,2324,2326,2328,2330,2332,2334],{"class":72,"line":73},[70,2325,540],{"class":76},[70,2327,386],{"class":264},[70,2329,389],{"class":76},[70,2331,386],{"class":264},[70,2333,1703],{"class":76},[70,2335,620],{"class":264},[70,2337,2338],{"class":72,"line":133},[70,2339,2026],{"class":264},[70,2341,2342,2344,2346,2348,2350,2352],{"class":72,"line":141},[70,2343,383],{"class":76},[70,2345,386],{"class":264},[70,2347,389],{"class":76},[70,2349,386],{"class":264},[70,2351,810],{"class":76},[70,2353,1727],{"class":264},[70,2355,2356],{"class":72,"line":240},[70,2357,2045],{"class":264},[15,2359,2360,2361,2363],{},"也只会向 ",[30,2362,810],{}," 中写入 11 个字节。",[15,2365,2366],{},"可以理解成：",[22,2368,2371],{"className":2369,"code":2370,"language":27,"meta":28},[25],"串口接收数据：\n\n┌───────────────────────────────────────────────┐\n│ 前 11 字节 │            剩余数据             │\n└───────────────────────────────────────────────┘\n     ↓\n写入 buffer\n\nstd::array\u003Cchar, 11>\n┌───┬───┬───┬─────┬────┐\n│ 0 │ 1 │ 2 │ ... │ 10 │\n└───┴───┴───┴─────┴────┘\n",[30,2372,2370],{"__ignoreMap":28},[15,2374,2375,2376,2378,2379,2381],{},"多出来的数据不会继续往这个 ",[30,2377,2247],{}," 后面写，因此不会把 ",[30,2380,2247],{}," 写越界。",[15,2383,2384],{},"剩余的数据仍然留在操作系统的串口接收缓冲区中，等待程序下一次读取。",[15,2386,2387],{},"例如串口一次收到了：",[22,2389,2392],{"className":2390,"code":2391,"language":27,"meta":28},[25],"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",[30,2393,2391],{"__ignoreMap":28},[15,2395,2396],{},"一共 26 个字节。",[15,2398,2399],{},"第一次读取 11 个字节：",[22,2401,2404],{"className":2402,"code":2403,"language":27,"meta":28},[25],"ABCDEFGHIJK\n",[30,2405,2403],{"__ignoreMap":28},[15,2407,2408],{},"剩下：",[22,2410,2413],{"className":2411,"code":2412,"language":27,"meta":28},[25],"LMNOPQRSTUVWXYZ\n",[30,2414,2412],{"__ignoreMap":28},[15,2416,2417],{},"还没有被程序取走。",[40,2419],{},[55,2421,2423,2424,2426],{"id":2422},"下一次读取时会从-array-的哪里开始写","下一次读取时，会从 ",[30,2425,2247],{}," 的哪里开始写？",[15,2428,2429],{},"如果下一次还是这样：",[22,2431,2432],{"className":210,"code":2005,"language":212,"meta":28,"style":28},[30,2433,2434,2448,2452,2466],{"__ignoreMap":28},[70,2435,2436,2438,2440,2442,2444,2446],{"class":72,"line":73},[70,2437,540],{"class":76},[70,2439,386],{"class":264},[70,2441,389],{"class":76},[70,2443,386],{"class":264},[70,2445,1703],{"class":76},[70,2447,620],{"class":264},[70,2449,2450],{"class":72,"line":133},[70,2451,2026],{"class":264},[70,2453,2454,2456,2458,2460,2462,2464],{"class":72,"line":141},[70,2455,383],{"class":76},[70,2457,386],{"class":264},[70,2459,389],{"class":76},[70,2461,386],{"class":264},[70,2463,810],{"class":76},[70,2465,1727],{"class":264},[70,2467,2468],{"class":72,"line":240},[70,2469,2045],{"class":264},[15,2471,2472],{},"那么会再次从：",[22,2474,2476],{"className":210,"code":2475,"language":212,"meta":28,"style":28},"buffer[0]\n",[30,2477,2478],{"__ignoreMap":28},[70,2479,2480,2483,2486],{"class":72,"line":73},[70,2481,2482],{"class":264},"buffer[",[70,2484,2485],{"class":124},"0",[70,2487,2488],{"class":264},"]\n",[15,2490,2491],{},"开始写。",[15,2493,2494,2495,2497],{},"也就是说，同一个 ",[30,2496,810],{}," 会被重新使用。",[15,2499,2500],{},"例如第一次读取后：",[22,2502,2505],{"className":2503,"code":2504,"language":27,"meta":28},[25],"buffer：\n\n┌───┬───┬───┬───┬────────┐\n│ A │ B │ C │ D │  ...   │\n└───┴───┴───┴───┴────────┘\n ↑\nbuffer[0]\n",[30,2506,2504],{"__ignoreMap":28},[15,2508,2509],{},"第二次再次读取：",[22,2511,2512],{"className":210,"code":2005,"language":212,"meta":28,"style":28},[30,2513,2514,2528,2532,2546],{"__ignoreMap":28},[70,2515,2516,2518,2520,2522,2524,2526],{"class":72,"line":73},[70,2517,540],{"class":76},[70,2519,386],{"class":264},[70,2521,389],{"class":76},[70,2523,386],{"class":264},[70,2525,1703],{"class":76},[70,2527,620],{"class":264},[70,2529,2530],{"class":72,"line":133},[70,2531,2026],{"class":264},[70,2533,2534,2536,2538,2540,2542,2544],{"class":72,"line":141},[70,2535,383],{"class":76},[70,2537,386],{"class":264},[70,2539,389],{"class":76},[70,2541,386],{"class":264},[70,2543,810],{"class":76},[70,2545,1727],{"class":264},[70,2547,2548],{"class":72,"line":240},[70,2549,2045],{"class":264},[15,2551,2552],{},"新收到的数据仍然从：",[22,2554,2555],{"className":210,"code":2475,"language":212,"meta":28,"style":28},[30,2556,2557],{"__ignoreMap":28},[70,2558,2559,2561,2563],{"class":72,"line":73},[70,2560,2482],{"class":264},[70,2562,2485],{"class":124},[70,2564,2488],{"class":264},[15,2566,2567],{},"开始写，因此会覆盖上一次保存的数据。",[15,2569,2366],{},[22,2571,2574],{"className":2572,"code":2573,"language":27,"meta":28},[25],"第一次读取：\n\nbuffer\n↓\nABCDEFGHIJK\n",[30,2575,2573],{"__ignoreMap":28},[15,2577,2578],{},"第二次读取：",[22,2580,2583],{"className":2581,"code":2582,"language":27,"meta":28},[25],"buffer\n↓\nLMNOPQRSTUV\n",[30,2584,2582],{"__ignoreMap":28},[15,2586,2587],{},"第二次的数据会把第一次的数据覆盖掉。",[15,2589,2590],{},"所以如果上一次的数据后面还需要使用，就应该在下一次读取之前：",[22,2592,2595],{"className":2593,"code":2594,"language":27,"meta":28},[25],"复制出去\n",[30,2596,2594],{"__ignoreMap":28},[15,2598,2599],{},"或者：",[22,2601,2604],{"className":2602,"code":2603,"language":27,"meta":28},[25],"解析处理掉\n",[30,2605,2603],{"__ignoreMap":28},[15,2607,2608,2609,2611],{},"不能指望同一个 ",[30,2610,2247],{}," 自动帮你保存每一次读取的数据。",[40,2613],{},[55,2615,2617,2618,2620],{"id":2616},"如果剩余数据不够填满整个-array-呢","如果剩余数据不够填满整个 ",[30,2619,2247],{}," 呢？",[15,2622,2623],{},"例如第一次已经读取：",[22,2625,2627],{"className":2626,"code":2403,"language":27,"meta":28},[25],[30,2628,2403],{"__ignoreMap":28},[15,2630,2631],{},"串口还剩：",[22,2633,2635],{"className":2634,"code":2412,"language":27,"meta":28},[25],[30,2636,2412],{"__ignoreMap":28},[15,2638,2639],{},"第二次读取 11 个字节：",[22,2641,2644],{"className":2642,"code":2643,"language":27,"meta":28},[25],"LMNOPQRSTUV\n",[30,2645,2643],{"__ignoreMap":28},[15,2647,2648],{},"这时候串口只剩：",[22,2650,2653],{"className":2651,"code":2652,"language":27,"meta":28},[25],"WXYZ\n",[30,2654,2652],{"__ignoreMap":28},[15,2656,2657],{},"只有 4 个字节。",[15,2659,2660],{},"如果第三次再次执行：",[22,2662,2663],{"className":210,"code":2005,"language":212,"meta":28,"style":28},[30,2664,2665,2679,2683,2697],{"__ignoreMap":28},[70,2666,2667,2669,2671,2673,2675,2677],{"class":72,"line":73},[70,2668,540],{"class":76},[70,2670,386],{"class":264},[70,2672,389],{"class":76},[70,2674,386],{"class":264},[70,2676,1703],{"class":76},[70,2678,620],{"class":264},[70,2680,2681],{"class":72,"line":133},[70,2682,2026],{"class":264},[70,2684,2685,2687,2689,2691,2693,2695],{"class":72,"line":141},[70,2686,383],{"class":76},[70,2688,386],{"class":264},[70,2690,389],{"class":76},[70,2692,386],{"class":264},[70,2694,810],{"class":76},[70,2696,1727],{"class":264},[70,2698,2699],{"class":72,"line":240},[70,2700,2045],{"class":264},[15,2702,2703],{},"因为 buffer 需要 11 个字节，所以过程会变成：",[22,2705,2708],{"className":2706,"code":2707,"language":27,"meta":28},[25],"先读取已有的：\n\nWXYZ\n↓\n只有 4 字节\n↓\n还差 7 字节\n↓\n继续阻塞等待\n↓\n以后又收到 7 字节\n↓\n累计达到 11 字节\n↓\nread() 返回\n",[30,2709,2707],{"__ignoreMap":28},[15,2711,2160],{},[12,2713,2714],{},[15,2715,2716,2718],{},[30,2717,2133],{}," 关注的是“把你提供的整个 buffer 填满”，而不是“一次串口发送对应一次读取”。",[15,2720,2721],{},"串口本质上是连续的字节流，并不会自动帮程序保存“这一条消息”和“下一条消息”的边界。",[40,2723],{},[55,2725,1026],{"id":2726},"关键函数说明-1",[1028,2728,2730],{"id":2729},"serialopenport_name-ec-1",[30,2731,1033],{},[15,2733,1036],{},[15,2735,1039],{},[22,2737,2738],{"className":210,"code":1042,"language":212,"meta":28,"style":28},[30,2739,2740],{"__ignoreMap":28},[70,2741,2742],{"class":72,"line":73},[70,2743,1042],{"class":264},[15,2745,2746],{},"例如：",[22,2748,2751],{"className":2749,"code":2750,"language":27,"meta":28},[25],"\u002Fdev\u002FttyUSB0\n\u002Fdev\u002FttyACM0\n\u002Fdev\u002Fpts\u002F3\n",[30,2752,2750],{"__ignoreMap":28},[22,2754,2755],{"className":210,"code":1063,"language":212,"meta":28,"style":28},[30,2756,2757],{"__ignoreMap":28},[70,2758,2759],{"class":72,"line":73},[70,2760,1063],{"class":264},[15,2762,2763],{},"用于接收错误信息。",[15,2765,2766],{},"如果打开失败：",[22,2768,2770],{"className":210,"code":2769,"language":212,"meta":28,"style":28},"if (ec)\n{\n    std::println(\"打开串口失败：{}\", ec.message());\n    return 1;\n}\n",[30,2771,2772,2779,2783,2801,2809],{"__ignoreMap":28},[70,2773,2774,2777],{"class":72,"line":73},[70,2775,2776],{"class":219},"if",[70,2778,477],{"class":264},[70,2780,2781],{"class":72,"line":133},[70,2782,289],{"class":264},[70,2784,2785,2787,2789,2791,2793,2795,2797,2799],{"class":72,"line":141},[70,2786,302],{"class":76},[70,2788,386],{"class":264},[70,2790,444],{"class":76},[70,2792,265],{"class":264},[70,2794,497],{"class":80},[70,2796,500],{"class":264},[70,2798,503],{"class":76},[70,2800,506],{"class":264},[70,2802,2803,2805,2807],{"class":72,"line":240},[70,2804,909],{"class":219},[70,2806,515],{"class":124},[70,2808,314],{"class":264},[70,2810,2811],{"class":72,"line":248},[70,2812,920],{"class":264},[40,2814],{},[1028,2816,2818],{"id":2817},"serialset_option-1",[30,2819,1078],{},[15,2821,2822],{},"作用：设置串口参数，例如波特率、数据位、校验位、停止位和流控。",[15,2824,2825],{},"本示例设置：",[22,2827,2830],{"className":2828,"code":2829,"language":27,"meta":28},[25],"波特率：115200\n数据位：8\n校验位：无\n停止位：1\n流控：无\n",[30,2831,2829],{"__ignoreMap":28},[15,2833,2834],{},"也就是常见的：",[22,2836,2839],{"className":2837,"code":2838,"language":27,"meta":28},[25],"115200 8N1\n",[30,2840,2838],{"__ignoreMap":28},[40,2842],{},[1028,2844,2846],{"id":2845},"stdarraychar-11-buffer",[30,2847,2848],{},"std::array\u003Cchar, 11> buffer{}",[15,2850,2851],{},"作用：创建一个 11 字节大小的接收缓冲区。",[22,2853,2854],{"className":210,"code":2051,"language":212,"meta":28,"style":28},[30,2855,2856],{"__ignoreMap":28},[70,2857,2858,2860,2862,2864,2866,2868,2870],{"class":72,"line":73},[70,2859,2058],{"class":76},[70,2861,1623],{"class":264},[70,2863,1626],{"class":219},[70,2865,274],{"class":264},[70,2867,1631],{"class":124},[70,2869,1634],{"class":219},[70,2871,1637],{"class":264},[15,2873,2874],{},"可以简单理解成：",[22,2876,2879],{"className":2877,"code":2878,"language":27,"meta":28},[25],"准备一块 11 字节的连续内存\n用来存放这一次读取到的串口数据\n",[30,2880,2878],{"__ignoreMap":28},[15,2882,2883],{},"它的容量固定为 11 字节。",[15,2885,2886],{},"如果串口中的数据超过 11 字节：",[22,2888,2891],{"className":2889,"code":2890,"language":27,"meta":28},[25],"本次最多读取 11 字节\n↓\n多出来的数据不会写越界\n↓\n剩余数据等待下一次读取\n",[30,2892,2890],{"__ignoreMap":28},[15,2894,2895],{},"如果下一次继续使用同一个：",[22,2897,2899],{"className":210,"code":2898,"language":212,"meta":28,"style":28},"buffer\n",[30,2900,2901],{"__ignoreMap":28},[70,2902,2903],{"class":72,"line":73},[70,2904,2898],{"class":264},[15,2906,2907],{},"那么新数据会再次从：",[22,2909,2910],{"className":210,"code":2475,"language":212,"meta":28,"style":28},[30,2911,2912],{"__ignoreMap":28},[70,2913,2914,2916,2918],{"class":72,"line":73},[70,2915,2482],{"class":264},[70,2917,2485],{"class":124},[70,2919,2488],{"class":264},[15,2921,2922],{},"开始写，覆盖上一次的数据。",[40,2924],{},[1028,2926,2928],{"id":2927},"boostasiobufferbuffer",[30,2929,2930],{},"boost::asio::buffer(buffer)",[15,2932,2933,2934,2936],{},"作用：把 ",[30,2935,810],{}," 对应的连续内存包装成 Asio 可以使用的 buffer。",[22,2938,2939],{"className":210,"code":2279,"language":212,"meta":28,"style":28},[30,2940,2941],{"__ignoreMap":28},[70,2942,2943,2945,2947,2949,2951,2953],{"class":72,"line":73},[70,2944,540],{"class":76},[70,2946,386],{"class":264},[70,2948,389],{"class":76},[70,2950,386],{"class":264},[70,2952,810],{"class":76},[70,2954,2296],{"class":264},[15,2956,2957],{},"可以简单理解成告诉 Asio：",[22,2959,2962],{"className":2960,"code":2961,"language":27,"meta":28},[25],"这块内存从哪里开始\n+\n这块内存有多大\n",[30,2963,2961],{"__ignoreMap":28},[15,2965,2966],{},"本例中相当于告诉 Asio：",[22,2968,2971],{"className":2969,"code":2970,"language":27,"meta":28},[25],"起始地址：buffer.data()\n\n可用空间：11 字节\n",[30,2972,2970],{"__ignoreMap":28},[15,2974,2975],{},"因此 Asio 不会向这块内存写入超过 11 字节的数据。",[15,2977,2978],{},"它本身不会复制数据，也不会拥有这块内存。",[40,2980],{},[1028,2982,2984],{"id":2983},"boostasioreadserial-boostasiobufferbuffer-ec",[30,2985,2986],{},"boost::asio::read(serial, boost::asio::buffer(buffer), ec)",[15,2988,2989],{},"作用：同步读取串口数据。",[22,2991,2993],{"className":210,"code":2992,"language":212,"meta":28,"style":28},"std::size_t n =\n    boost::asio::read(\n        serial,\n        boost::asio::buffer(buffer),\n        ec);\n",[30,2994,2995,3007,3021,3026,3040],{"__ignoreMap":28},[70,2996,2997,2999,3001,3003,3005],{"class":72,"line":73},[70,2998,2058],{"class":76},[70,3000,386],{"class":264},[70,3002,779],{"class":219},[70,3004,782],{"class":264},[70,3006,1689],{"class":219},[70,3008,3009,3011,3013,3015,3017,3019],{"class":72,"line":133},[70,3010,383],{"class":76},[70,3012,386],{"class":264},[70,3014,389],{"class":76},[70,3016,386],{"class":264},[70,3018,1703],{"class":76},[70,3020,620],{"class":264},[70,3022,3023],{"class":72,"line":141},[70,3024,3025],{"class":264},"        serial,\n",[70,3027,3028,3030,3032,3034,3036,3038],{"class":72,"line":240},[70,3029,626],{"class":76},[70,3031,386],{"class":264},[70,3033,389],{"class":76},[70,3035,386],{"class":264},[70,3037,810],{"class":76},[70,3039,1727],{"class":264},[70,3041,3042],{"class":72,"line":248},[70,3043,3044],{"class":264},"        ec);\n",[15,3046,3047],{},"其中：",[22,3049,3051],{"className":210,"code":3050,"language":212,"meta":28,"style":28},"serial\n",[30,3052,3053],{"__ignoreMap":28},[70,3054,3055],{"class":72,"line":73},[70,3056,3050],{"class":264},[15,3058,3059],{},"表示从哪个串口读取。",[22,3061,3062],{"className":210,"code":2279,"language":212,"meta":28,"style":28},[30,3063,3064],{"__ignoreMap":28},[70,3065,3066,3068,3070,3072,3074,3076],{"class":72,"line":73},[70,3067,540],{"class":76},[70,3069,386],{"class":264},[70,3071,389],{"class":76},[70,3073,386],{"class":264},[70,3075,810],{"class":76},[70,3077,2296],{"class":264},[15,3079,2203],{},[22,3081,3084],{"className":3082,"code":3083,"language":27,"meta":28},[25],"接收到的数据放到哪里\n+\n需要读取多少数据\n",[30,3085,3083],{"__ignoreMap":28},[22,3087,3088],{"className":210,"code":1063,"language":212,"meta":28,"style":28},[30,3089,3090],{"__ignoreMap":28},[70,3091,3092],{"class":72,"line":73},[70,3093,1063],{"class":264},[15,3095,2763],{},[15,3097,3098],{},"返回值：",[22,3100,3102],{"className":210,"code":3101,"language":212,"meta":28,"style":28},"std::size_t n\n",[30,3103,3104],{"__ignoreMap":28},[70,3105,3106,3108,3110,3112],{"class":72,"line":73},[70,3107,2058],{"class":76},[70,3109,386],{"class":264},[70,3111,779],{"class":219},[70,3113,3114],{"class":264}," n\n",[15,3116,3117],{},"表示实际读取到的字节数。",[15,3119,3120],{},"本例中正常读取完成后：",[22,3122,3125],{"className":3123,"code":3124,"language":27,"meta":28},[25],"n = 11\n",[30,3126,3124],{"__ignoreMap":28},[15,3128,3129],{},"所以可以简单理解为：",[12,3131,3132],{},[15,3133,3134,3136],{},[30,3135,2133],{}," 会同步阻塞读取数据，直到指定的整个 buffer 被填满或者发生错误。",[40,3138],{},[1028,3140,3142],{"id":3141},"stdstring-msgbufferdata-n",[30,3143,3144],{},"std::string msg(buffer.data(), n)",[15,3146,3147],{},"作用：把接收到的字节转换成字符串，方便输出。",[22,3149,3151],{"className":210,"code":3150,"language":212,"meta":28,"style":28},"buffer.data()\n",[30,3152,3153],{"__ignoreMap":28},[70,3154,3155,3158,3160],{"class":72,"line":73},[70,3156,3157],{"class":264},"buffer.",[70,3159,1812],{"class":76},[70,3161,3162],{"class":264},"()\n",[15,3164,3165,3166,38],{},"表示 buffer 的",[924,3167,3168],{},"起始地址",[22,3170,3172],{"className":210,"code":3171,"language":212,"meta":28,"style":28},"n\n",[30,3173,3174],{"__ignoreMap":28},[70,3175,3176],{"class":72,"line":73},[70,3177,3171],{"class":264},[15,3179,3117],{},[15,3181,3182],{},"因此：",[22,3184,3186],{"className":210,"code":3185,"language":212,"meta":28,"style":28},"std::string msg(buffer.data(), n);\n",[30,3187,3188],{"__ignoreMap":28},[70,3189,3190,3192,3194,3197,3200,3202,3204,3207,3209,3212,3215],{"class":72,"line":73},[70,3191,2058],{"class":76},[70,3193,386],{"class":264},[70,3195,3196],{"class":76},"string",[70,3198,3199],{"class":76}," msg",[70,3201,265],{"class":264},[70,3203,810],{"class":76},[70,3205,3206],{"class":264},".",[70,3208,1812],{"class":76},[70,3210,3211],{"class":264},"(), ",[70,3213,3214],{"class":76},"n",[70,3216,898],{"class":264},[15,3218,2366],{},[22,3220,3223],{"className":3221,"code":3222,"language":27,"meta":28},[25],"从 buffer 的开头\n取出前 n 个字节\n↓\n构造一个 std::string\n",[30,3224,3222],{"__ignoreMap":28},[15,3226,3227],{},"一句话记住：",[12,3229,3230],{},[15,3231,3232,3234,3235,3238],{},[30,3233,2133],{}," 只会向你提供的 buffer 范围内写数据；如果串口里还有更多数据，多出来的部分会留待下一次读取，而下一次使用同一个 buffer 时，会重新从 ",[30,3236,3237],{},"buffer[0]"," 开始写并覆盖旧数据。",[40,3240],{},[43,3242,3244,3247],{"id":3243},"some相关的读取函数不常用",[30,3245,3246],{},"some()","相关的读取函数（不常用）",[55,3249,3251,3254,3255,3258,3259,3254,3262,3265],{"id":3250},"read-write-和-read_some-write_some-的区别",[30,3252,3253],{},"read()"," \u002F ",[30,3256,3257],{},"write()"," 和 ",[30,3260,3261],{},"read_some()",[30,3263,3264],{},"write_some()"," 的区别",[15,3267,3268],{},"Boost.Asio 的同步读写接口可以分成两组：",[22,3270,3273],{"className":3271,"code":3272,"language":27,"meta":28},[25],"boost::asio::read()\nboost::asio::write()\n",[30,3274,3272],{"__ignoreMap":28},[15,3276,3277],{},"和：",[22,3279,3282],{"className":3280,"code":3281,"language":27,"meta":28},[25],"serial.read_some()\nserial.write_some()\n",[30,3283,3281],{"__ignoreMap":28},[15,3285,3286],{},"它们最大的区别是：",[12,3288,3289],{},[15,3290,3291,3254,3293,3295,3296,3299,3254,3301,3303],{},[30,3292,3253],{},[30,3294,3257],{}," 会尽量把整个指定 buffer 处理完；",[3297,3298],"br",{},[30,3300,3261],{},[30,3302,3264],{}," 只进行一次读写操作，实际处理多少就返回多少。",[40,3305],{},[1028,3307,3309],{"id":3308},"boostasioread",[30,3310,2133],{},[15,3312,2746],{},[22,3314,3316],{"className":210,"code":3315,"language":212,"meta":28,"style":28},"std::array\u003Cchar, 11> buffer{};\n\nstd::size_t n =\n    boost::asio::read(\n        serial,\n        boost::asio::buffer(buffer),\n        ec);\n",[30,3317,3318,3334,3338,3350,3364,3368,3382],{"__ignoreMap":28},[70,3319,3320,3322,3324,3326,3328,3330,3332],{"class":72,"line":73},[70,3321,2058],{"class":76},[70,3323,1623],{"class":264},[70,3325,1626],{"class":219},[70,3327,274],{"class":264},[70,3329,1631],{"class":124},[70,3331,1634],{"class":219},[70,3333,1637],{"class":264},[70,3335,3336],{"class":72,"line":133},[70,3337,252],{"emptyLinePlaceholder":251},[70,3339,3340,3342,3344,3346,3348],{"class":72,"line":141},[70,3341,2058],{"class":76},[70,3343,386],{"class":264},[70,3345,779],{"class":219},[70,3347,782],{"class":264},[70,3349,1689],{"class":219},[70,3351,3352,3354,3356,3358,3360,3362],{"class":72,"line":240},[70,3353,383],{"class":76},[70,3355,386],{"class":264},[70,3357,389],{"class":76},[70,3359,386],{"class":264},[70,3361,1703],{"class":76},[70,3363,620],{"class":264},[70,3365,3366],{"class":72,"line":248},[70,3367,3025],{"class":264},[70,3369,3370,3372,3374,3376,3378,3380],{"class":72,"line":255},[70,3371,626],{"class":76},[70,3373,386],{"class":264},[70,3375,389],{"class":76},[70,3377,386],{"class":264},[70,3379,810],{"class":76},[70,3381,1727],{"class":264},[70,3383,3384],{"class":72,"line":286},[70,3385,3044],{"class":264},[15,3387,3388],{},"这里 buffer 大小是 11 字节。",[15,3390,3391,3393],{},[30,3392,2133],{}," 默认会一直读取，直到：",[22,3395,3398],{"className":3396,"code":3397,"language":27,"meta":28},[25],"累计读取到 11 字节\n",[30,3399,3397],{"__ignoreMap":28},[15,3401,2599],{},[22,3403,3406],{"className":3404,"code":3405,"language":27,"meta":28},[25],"发生错误\n",[30,3407,3405],{"__ignoreMap":28},[15,3409,3410],{},"例如串口的数据并不是一次性全部到达：",[22,3412,3415],{"className":3413,"code":3414,"language":27,"meta":28},[25],"第一次来了 3 字节\n第二次来了 5 字节\n第三次来了 3 字节\n",[30,3416,3414],{"__ignoreMap":28},[15,3418,3419,3421],{},[30,3420,3253],{}," 可以理解成：",[22,3423,3426],{"className":3424,"code":3425,"language":27,"meta":28},[25],"第一次读取 3 字节\n↓\n还差 8 字节\n↓\n继续等\n\n第二次读取 5 字节\n↓\n还差 3 字节\n↓\n继续等\n\n第三次读取 3 字节\n↓\n累计 11 字节\n↓\nread() 返回\n",[30,3427,3425],{"__ignoreMap":28},[15,3429,2160],{},[22,3431,3433],{"className":210,"code":3432,"language":212,"meta":28,"style":28},"boost::asio::read(...)\n",[30,3434,3435],{"__ignoreMap":28},[70,3436,3437,3439,3441,3443,3445,3447],{"class":72,"line":73},[70,3438,540],{"class":76},[70,3440,386],{"class":264},[70,3442,389],{"class":76},[70,3444,386],{"class":264},[70,3446,1703],{"class":76},[70,3448,3449],{"class":264},"(...)\n",[15,3451,2874],{},[12,3453,3454],{},[15,3455,3456],{},"我要把这个 buffer 读满再返回。",[40,3458],{},[1028,3460,3462],{"id":3461},"serialread_some",[30,3463,3464],{},"serial.read_some()",[15,3466,2746],{},[22,3468,3470],{"className":210,"code":3469,"language":212,"meta":28,"style":28},"std::array\u003Cchar, 100> buffer{};\n\nstd::size_t n =\n    serial.read_some(\n        boost::asio::buffer(buffer),\n        ec);\n",[30,3471,3472,3489,3493,3505,3514,3528],{"__ignoreMap":28},[70,3473,3474,3476,3478,3480,3482,3485,3487],{"class":72,"line":73},[70,3475,2058],{"class":76},[70,3477,1623],{"class":264},[70,3479,1626],{"class":219},[70,3481,274],{"class":264},[70,3483,3484],{"class":124},"100",[70,3486,1634],{"class":219},[70,3488,1637],{"class":264},[70,3490,3491],{"class":72,"line":133},[70,3492,252],{"emptyLinePlaceholder":251},[70,3494,3495,3497,3499,3501,3503],{"class":72,"line":141},[70,3496,2058],{"class":76},[70,3498,386],{"class":264},[70,3500,779],{"class":219},[70,3502,782],{"class":264},[70,3504,1689],{"class":219},[70,3506,3507,3509,3512],{"class":72,"line":240},[70,3508,463],{"class":264},[70,3510,3511],{"class":76},"read_some",[70,3513,620],{"class":264},[70,3515,3516,3518,3520,3522,3524,3526],{"class":72,"line":248},[70,3517,626],{"class":76},[70,3519,386],{"class":264},[70,3521,389],{"class":76},[70,3523,386],{"class":264},[70,3525,810],{"class":76},[70,3527,1727],{"class":264},[70,3529,3530],{"class":72,"line":255},[70,3531,3044],{"class":264},[15,3533,3534],{},"虽然 buffer 可以装 100 字节，但是：",[22,3536,3538],{"className":210,"code":3537,"language":212,"meta":28,"style":28},"read_some()\n",[30,3539,3540],{"__ignoreMap":28},[70,3541,3542,3544],{"class":72,"line":73},[70,3543,3511],{"class":76},[70,3545,3162],{"class":264},[15,3547,3548],{},"并不要求一定读取 100 字节。",[15,3550,3551],{},"如果当前只读到了 8 字节，就可能直接：",[22,3553,3556],{"className":3554,"code":3555,"language":27,"meta":28},[25],"n = 8\n",[30,3557,3555],{"__ignoreMap":28},[15,3559,3560],{},"然后返回。",[15,3562,2746],{},[22,3564,3567],{"className":3565,"code":3566,"language":27,"meta":28},[25],"buffer 最大容量：100 字节\n\n当前串口可以读取：8 字节\n↓\nread_some()\n↓\n读取 8 字节\n↓\n立即返回\n",[30,3568,3566],{"__ignoreMap":28},[15,3570,2160],{},[22,3572,3573],{"className":210,"code":3537,"language":212,"meta":28,"style":28},[30,3574,3575],{"__ignoreMap":28},[70,3576,3577,3579],{"class":72,"line":73},[70,3578,3511],{"class":76},[70,3580,3162],{"class":264},[15,3582,2874],{},[12,3584,3585],{},[15,3586,3587],{},"有多少先给我读一些，不要求把整个 buffer 填满。",[40,3589],{},[1028,3591,3593],{"id":3592},"boostasiowrite",[30,3594,1022],{},[15,3596,2746],{},[22,3598,3600],{"className":210,"code":3599,"language":212,"meta":28,"style":28},"std::string msg = \"hello asio\";\n\nstd::size_t n =\n    boost::asio::write(\n        serial,\n        boost::asio::buffer(msg),\n        ec);\n",[30,3601,3602,3614,3618,3630,3644,3648,3663],{"__ignoreMap":28},[70,3603,3604,3606,3608,3610,3612],{"class":72,"line":73},[70,3605,2058],{"class":76},[70,3607,745],{"class":264},[70,3609,308],{"class":219},[70,3611,1973],{"class":80},[70,3613,314],{"class":264},[70,3615,3616],{"class":72,"line":133},[70,3617,252],{"emptyLinePlaceholder":251},[70,3619,3620,3622,3624,3626,3628],{"class":72,"line":141},[70,3621,2058],{"class":76},[70,3623,386],{"class":264},[70,3625,779],{"class":219},[70,3627,782],{"class":264},[70,3629,1689],{"class":219},[70,3631,3632,3634,3636,3638,3640,3642],{"class":72,"line":240},[70,3633,383],{"class":76},[70,3635,386],{"class":264},[70,3637,389],{"class":76},[70,3639,386],{"class":264},[70,3641,796],{"class":76},[70,3643,620],{"class":264},[70,3645,3646],{"class":72,"line":248},[70,3647,3025],{"class":264},[70,3649,3650,3652,3654,3656,3658,3660],{"class":72,"line":255},[70,3651,626],{"class":76},[70,3653,386],{"class":264},[70,3655,389],{"class":76},[70,3657,386],{"class":264},[70,3659,810],{"class":76},[70,3661,3662],{"class":264},"(msg),\n",[70,3664,3665],{"class":72,"line":286},[70,3666,3044],{"class":264},[15,3668,3669],{},"假设：",[22,3671,3674],{"className":3672,"code":3673,"language":27,"meta":28},[25],"msg = 10 字节\n",[30,3675,3673],{"__ignoreMap":28},[15,3677,3678,3680],{},[30,3679,1022],{}," 会一直尝试写，直到：",[22,3682,3685],{"className":3683,"code":3684,"language":27,"meta":28},[25],"整个 10 字节都写完\n",[30,3686,3684],{"__ignoreMap":28},[15,3688,2599],{},[22,3690,3692],{"className":3691,"code":3405,"language":27,"meta":28},[25],[30,3693,3405],{"__ignoreMap":28},[15,3695,3696],{},"例如底层第一次只能写 4 字节：",[22,3698,3701],{"className":3699,"code":3700,"language":27,"meta":28},[25],"准备发送 10 字节\n↓\n第一次写 4 字节\n↓\n还剩 6 字节\n↓\n继续写\n↓\n又写 6 字节\n↓\n全部完成\n↓\nwrite() 返回 n = 10\n",[30,3702,3700],{"__ignoreMap":28},[15,3704,2160],{},[22,3706,3708],{"className":210,"code":3707,"language":212,"meta":28,"style":28},"boost::asio::write(...)\n",[30,3709,3710],{"__ignoreMap":28},[70,3711,3712,3714,3716,3718,3720,3722],{"class":72,"line":73},[70,3713,540],{"class":76},[70,3715,386],{"class":264},[70,3717,389],{"class":76},[70,3719,386],{"class":264},[70,3721,796],{"class":76},[70,3723,3449],{"class":264},[15,3725,2874],{},[12,3727,3728],{},[15,3729,3730],{},"我要把整个 buffer 都写出去再返回。",[40,3732],{},[1028,3734,3736],{"id":3735},"serialwrite_some",[30,3737,3738],{},"serial.write_some()",[15,3740,2746],{},[22,3742,3744],{"className":210,"code":3743,"language":212,"meta":28,"style":28},"std::string msg = \"hello asio\";\n\nstd::size_t n =\n    serial.write_some(\n        boost::asio::buffer(msg),\n        ec);\n",[30,3745,3746,3758,3762,3774,3783,3797],{"__ignoreMap":28},[70,3747,3748,3750,3752,3754,3756],{"class":72,"line":73},[70,3749,2058],{"class":76},[70,3751,745],{"class":264},[70,3753,308],{"class":219},[70,3755,1973],{"class":80},[70,3757,314],{"class":264},[70,3759,3760],{"class":72,"line":133},[70,3761,252],{"emptyLinePlaceholder":251},[70,3763,3764,3766,3768,3770,3772],{"class":72,"line":141},[70,3765,2058],{"class":76},[70,3767,386],{"class":264},[70,3769,779],{"class":219},[70,3771,782],{"class":264},[70,3773,1689],{"class":219},[70,3775,3776,3778,3781],{"class":72,"line":240},[70,3777,463],{"class":264},[70,3779,3780],{"class":76},"write_some",[70,3782,620],{"class":264},[70,3784,3785,3787,3789,3791,3793,3795],{"class":72,"line":248},[70,3786,626],{"class":76},[70,3788,386],{"class":264},[70,3790,389],{"class":76},[70,3792,386],{"class":264},[70,3794,810],{"class":76},[70,3796,3662],{"class":264},[70,3798,3799],{"class":72,"line":255},[70,3800,3044],{"class":264},[15,3802,3803],{},"即使：",[22,3805,3808],{"className":3806,"code":3807,"language":27,"meta":28},[25],"msg 一共有 10 字节\n",[30,3809,3807],{"__ignoreMap":28},[15,3811,3812],{},"这一次调用也不保证一定全部写完。",[15,3814,3815],{},"例如可能：",[22,3817,3820],{"className":3818,"code":3819,"language":27,"meta":28},[25],"准备发送：10 字节\n↓\nwrite_some()\n↓\n实际写入：4 字节\n↓\n返回 n = 4\n",[30,3821,3819],{"__ignoreMap":28},[15,3823,3824],{},"剩下的：",[22,3826,3829],{"className":3827,"code":3828,"language":27,"meta":28},[25],"6 字节\n",[30,3830,3828],{"__ignoreMap":28},[15,3832,3833],{},"需要程序后续继续处理。",[15,3835,2160],{},[22,3837,3839],{"className":210,"code":3838,"language":212,"meta":28,"style":28},"write_some()\n",[30,3840,3841],{"__ignoreMap":28},[70,3842,3843,3845],{"class":72,"line":73},[70,3844,3780],{"class":76},[70,3846,3162],{"class":264},[15,3848,2874],{},[12,3850,3851],{},[15,3852,3853],{},"这一次能写多少就先写多少，然后告诉我实际写了多少。",[40,3855],{},[55,3857,3859],{"id":3858},"四个-api-对比","四个 API 对比",[3861,3862,3863,3879],"table",{},[3864,3865,3866],"thead",{},[3867,3868,3869,3873,3876],"tr",{},[3870,3871,3872],"th",{},"API",[3870,3874,3875],{},"类型",[3870,3877,3878],{},"是否要求整个 buffer 完成",[3880,3881,3882,3895,3906,3918],"tbody",{},[3867,3883,3884,3889,3892],{},[3885,3886,3887],"td",{},[30,3888,2133],{},[3885,3890,3891],{},"同步读取",[3885,3893,3894],{},"是，默认一直读到整个 buffer 被填满或发生错误",[3867,3896,3897,3901,3903],{},[3885,3898,3899],{},[30,3900,3464],{},[3885,3902,3891],{},[3885,3904,3905],{},"否，读取到一些数据就可以返回",[3867,3907,3908,3912,3915],{},[3885,3909,3910],{},[30,3911,1022],{},[3885,3913,3914],{},"同步写入",[3885,3916,3917],{},"是，默认一直写到整个 buffer 写完或发生错误",[3867,3919,3920,3924,3926],{},[3885,3921,3922],{},[30,3923,3738],{},[3885,3925,3914],{},[3885,3927,3928],{},"否，这次实际写多少就返回多少",[15,3930,3931],{},"可以直接记成：",[22,3933,3936],{"className":3934,"code":3935,"language":27,"meta":28},[25],"read()\n→ 读满\n\nread_some()\n→ 读一些\n",[30,3937,3935],{"__ignoreMap":28},[22,3939,3942],{"className":3940,"code":3941,"language":27,"meta":28},[25],"write()\n→ 写完\n\nwrite_some()\n→ 写一些\n",[30,3943,3941],{"__ignoreMap":28},[40,3945],{},[55,3947,3949,3950,3254,3952,3954,3955,3957],{"id":3948},"为什么-read-write-不是-serial-的成员函数","为什么 ",[30,3951,3253],{},[30,3953,3257],{}," 不是 ",[30,3956,413],{}," 的成员函数？",[15,3959,3960],{},"你会发现：",[22,3962,3964],{"className":210,"code":3963,"language":212,"meta":28,"style":28},"serial.read_some(...)\nserial.write_some(...)\n",[30,3965,3966,3975],{"__ignoreMap":28},[70,3967,3968,3971,3973],{"class":72,"line":73},[70,3969,3970],{"class":264},"serial.",[70,3972,3511],{"class":76},[70,3974,3449],{"class":264},[70,3976,3977,3979,3981],{"class":72,"line":133},[70,3978,3970],{"class":264},[70,3980,3780],{"class":76},[70,3982,3449],{"class":264},[15,3984,3985],{},"属于：",[22,3987,3988],{"className":210,"code":3050,"language":212,"meta":28,"style":28},[30,3989,3990],{"__ignoreMap":28},[70,3991,3992],{"class":72,"line":73},[70,3993,3050],{"class":264},[15,3995,3996],{},"对象自己的成员函数。",[15,3998,3999],{},"但是：",[22,4001,4003],{"className":210,"code":4002,"language":212,"meta":28,"style":28},"boost::asio::read(...)\nboost::asio::write(...)\n",[30,4004,4005,4019],{"__ignoreMap":28},[70,4006,4007,4009,4011,4013,4015,4017],{"class":72,"line":73},[70,4008,540],{"class":76},[70,4010,386],{"class":264},[70,4012,389],{"class":76},[70,4014,386],{"class":264},[70,4016,1703],{"class":76},[70,4018,3449],{"class":264},[70,4020,4021,4023,4025,4027,4029,4031],{"class":72,"line":133},[70,4022,540],{"class":76},[70,4024,386],{"class":264},[70,4026,389],{"class":76},[70,4028,386],{"class":264},[70,4030,796],{"class":76},[70,4032,3449],{"class":264},[15,4034,4035],{},"却是：",[22,4037,4039],{"className":210,"code":4038,"language":212,"meta":28,"style":28},"boost::asio\n",[30,4040,4041],{"__ignoreMap":28},[70,4042,4043,4045],{"class":72,"line":73},[70,4044,540],{"class":76},[70,4046,4047],{"class":264},"::asio\n",[15,4049,4050],{},"命名空间中的普通函数。",[15,4052,4053],{},"这是因为：",[22,4055,4058],{"className":4056,"code":4057,"language":27,"meta":28},[25],"read_some()\nwrite_some()\n",[30,4059,4057],{"__ignoreMap":28},[15,4061,4062],{},"属于底层的单次 I\u002FO 操作。",[15,4064,4065],{},"而：",[22,4067,4069],{"className":4068,"code":3272,"language":27,"meta":28},[25],[30,4070,3272],{"__ignoreMap":28},[15,4072,4073],{},"属于更高层的组合操作。",[15,4075,2746],{},[22,4077,4079],{"className":210,"code":4078,"language":212,"meta":28,"style":28},"boost::asio::write(\n    serial,\n    boost::asio::buffer(msg),\n    ec);\n",[30,4080,4081,4095,4099,4113],{"__ignoreMap":28},[70,4082,4083,4085,4087,4089,4091,4093],{"class":72,"line":73},[70,4084,540],{"class":76},[70,4086,386],{"class":264},[70,4088,389],{"class":76},[70,4090,386],{"class":264},[70,4092,796],{"class":76},[70,4094,620],{"class":264},[70,4096,4097],{"class":72,"line":133},[70,4098,2026],{"class":264},[70,4100,4101,4103,4105,4107,4109,4111],{"class":72,"line":141},[70,4102,383],{"class":76},[70,4104,386],{"class":264},[70,4106,389],{"class":76},[70,4108,386],{"class":264},[70,4110,810],{"class":76},[70,4112,3662],{"class":264},[70,4114,4115],{"class":72,"line":240},[70,4116,2045],{"class":264},[15,4118,4119],{},"可以粗略理解成内部不断进行：",[22,4121,4124],{"className":4122,"code":4123,"language":27,"meta":28},[25],"write_some()\n↓\n没写完\n↓\n继续 write_some()\n↓\n没写完\n↓\n继续\n↓\n整个 buffer 写完\n",[30,4125,4123],{"__ignoreMap":28},[15,4127,4128],{},"同理：",[22,4130,4131],{"className":210,"code":3432,"language":212,"meta":28,"style":28},[30,4132,4133],{"__ignoreMap":28},[70,4134,4135,4137,4139,4141,4143,4145],{"class":72,"line":73},[70,4136,540],{"class":76},[70,4138,386],{"class":264},[70,4140,389],{"class":76},[70,4142,386],{"class":264},[70,4144,1703],{"class":76},[70,4146,3449],{"class":264},[15,4148,4149],{},"可以粗略理解成：",[22,4151,4154],{"className":4152,"code":4153,"language":27,"meta":28},[25],"read_some()\n↓\nbuffer 还没满\n↓\n继续 read_some()\n↓\n还没满\n↓\n继续\n↓\n整个 buffer 填满\n",[30,4155,4153],{"__ignoreMap":28},[15,4157,4158],{},"因此可以理解为：",[22,4160,4163],{"className":4161,"code":4162,"language":27,"meta":28},[25],"read_some() \u002F write_some()\n        ↓\n底层单次操作\n\nread() \u002F write()\n        ↓\n建立在底层操作之上的组合操作\n",[30,4164,4162],{"__ignoreMap":28},[15,4166,4167,4168,3258,4170,4172],{},"而且 ",[30,4169,2133],{},[30,4171,1022],{}," 不只可以用于串口，还可以用于其他符合 Asio 读写接口要求的对象，例如 socket。",[15,4174,4175],{},"所以 Asio 没有给每一种设备都分别设计：",[22,4177,4179],{"className":210,"code":4178,"language":212,"meta":28,"style":28},"serial.read()\nserial.write()\n\nsocket.read()\nsocket.write()\n",[30,4180,4181,4189,4197,4201,4210],{"__ignoreMap":28},[70,4182,4183,4185,4187],{"class":72,"line":73},[70,4184,3970],{"class":264},[70,4186,1703],{"class":76},[70,4188,3162],{"class":264},[70,4190,4191,4193,4195],{"class":72,"line":133},[70,4192,3970],{"class":264},[70,4194,796],{"class":76},[70,4196,3162],{"class":264},[70,4198,4199],{"class":72,"line":141},[70,4200,252],{"emptyLinePlaceholder":251},[70,4202,4203,4206,4208],{"class":72,"line":240},[70,4204,4205],{"class":264},"socket.",[70,4207,1703],{"class":76},[70,4209,3162],{"class":264},[70,4211,4212,4214,4216],{"class":72,"line":248},[70,4213,4205],{"class":264},[70,4215,796],{"class":76},[70,4217,3162],{"class":264},[15,4219,4220],{},"而是统一提供：",[22,4222,4223],{"className":210,"code":4002,"language":212,"meta":28,"style":28},[30,4224,4225,4239],{"__ignoreMap":28},[70,4226,4227,4229,4231,4233,4235,4237],{"class":72,"line":73},[70,4228,540],{"class":76},[70,4230,386],{"class":264},[70,4232,389],{"class":76},[70,4234,386],{"class":264},[70,4236,1703],{"class":76},[70,4238,3449],{"class":264},[70,4240,4241,4243,4245,4247,4249,4251],{"class":72,"line":133},[70,4242,540],{"class":76},[70,4244,386],{"class":264},[70,4246,389],{"class":76},[70,4248,386],{"class":264},[70,4250,796],{"class":76},[70,4252,3449],{"class":264},[40,4254],{},[55,4256,4258],{"id":4257},"使用时怎么选择","使用时怎么选择？",[15,4260,4261],{},"如果你的需求是：",[22,4263,4266],{"className":4264,"code":4265,"language":27,"meta":28},[25],"我明确知道需要读取固定长度的数据\n",[30,4267,4265],{"__ignoreMap":28},[15,4269,2746],{},[22,4271,4274],{"className":4272,"code":4273,"language":27,"meta":28},[25],"固定读取 8 字节\n固定读取 32 字节\n固定读取一个已知长度的数据块\n",[30,4275,4273],{"__ignoreMap":28},[15,4277,4278],{},"可以使用：",[22,4280,4282],{"className":210,"code":4281,"language":212,"meta":28,"style":28},"boost::asio::read()\n",[30,4283,4284],{"__ignoreMap":28},[70,4285,4286,4288,4290,4292,4294,4296],{"class":72,"line":73},[70,4287,540],{"class":76},[70,4289,386],{"class":264},[70,4291,389],{"class":76},[70,4293,386],{"class":264},[70,4295,1703],{"class":76},[70,4297,3162],{"class":264},[15,4299,4261],{},[22,4301,4304],{"className":4302,"code":4303,"language":27,"meta":28},[25],"串口来了多少数据我先取多少\n",[30,4305,4303],{"__ignoreMap":28},[15,4307,4308],{},"则更适合：",[22,4310,4311],{"className":210,"code":3537,"language":212,"meta":28,"style":28},[30,4312,4313],{"__ignoreMap":28},[70,4314,4315,4317],{"class":72,"line":73},[70,4316,3511],{"class":76},[70,4318,3162],{"class":264},[15,4320,4321],{},"发送也是一样。",[15,4323,4261],{},[22,4325,4328],{"className":4326,"code":4327,"language":27,"meta":28},[25],"我要把整个 buffer 全部发送出去\n",[30,4329,4327],{"__ignoreMap":28},[15,4331,4332],{},"通常直接使用：",[22,4334,4336],{"className":210,"code":4335,"language":212,"meta":28,"style":28},"boost::asio::write()\n",[30,4337,4338],{"__ignoreMap":28},[70,4339,4340,4342,4344,4346,4348,4350],{"class":72,"line":73},[70,4341,540],{"class":76},[70,4343,386],{"class":264},[70,4345,389],{"class":76},[70,4347,386],{"class":264},[70,4349,796],{"class":76},[70,4351,3162],{"class":264},[15,4353,4354],{},"如果你希望：",[22,4356,4359],{"className":4357,"code":4358,"language":27,"meta":28},[25],"自己控制每一次底层写操作\n",[30,4360,4358],{"__ignoreMap":28},[15,4362,4363],{},"才会直接使用：",[22,4365,4366],{"className":210,"code":3838,"language":212,"meta":28,"style":28},[30,4367,4368],{"__ignoreMap":28},[70,4369,4370,4372],{"class":72,"line":73},[70,4371,3780],{"class":76},[70,4373,3162],{"class":264},[15,4375,3227],{},[12,4377,4378],{},[15,4379,4380,3254,4382,4384,4385,3254,4387,4389],{},[30,4381,3253],{},[30,4383,3257],{}," 是“把整个 buffer 处理完”；",[30,4386,3261],{},[30,4388,3264],{}," 是“这一次能处理多少就先处理多少”。",[40,4391],{},[43,4393,4395,4396,4398],{"id":4394},"示例-3普通-main-里异步发送串口数据","示例 3：普通 ",[30,4397,182],{}," 里异步发送串口数据",[55,4400,186],{"id":4401},"程序目标-2",[15,4403,4404],{},"前面的示例 1 使用：",[22,4406,4407],{"className":210,"code":4335,"language":212,"meta":28,"style":28},[30,4408,4409],{"__ignoreMap":28},[70,4410,4411,4413,4415,4417,4419,4421],{"class":72,"line":73},[70,4412,540],{"class":76},[70,4414,386],{"class":264},[70,4416,389],{"class":76},[70,4418,386],{"class":264},[70,4420,796],{"class":76},[70,4422,3162],{"class":264},[15,4424,4425],{},"同步发送数据。",[15,4427,4428],{},"这一节把它改成异步版本：",[22,4430,4432],{"className":210,"code":4431,"language":212,"meta":28,"style":28},"boost::asio::async_write()\n",[30,4433,4434],{"__ignoreMap":28},[70,4435,4436,4438,4440,4442,4444,4447],{"class":72,"line":73},[70,4437,540],{"class":76},[70,4439,386],{"class":264},[70,4441,389],{"class":76},[70,4443,386],{"class":264},[70,4445,4446],{"class":76},"async_write",[70,4448,3162],{"class":264},[15,4450,189,4451,4453],{},[30,4452,168],{},"，然后异步发送：",[22,4455,4458],{"className":4456,"code":4457,"language":27,"meta":28},[25],"hello async\n",[30,4459,4457],{"__ignoreMap":28},[15,4461,201,4462,4464],{},[30,4463,172],{}," 读取数据。",[15,4466,4467],{},"整个执行流程是：",[22,4469,4472],{"className":4470,"code":4471,"language":27,"meta":28},[25],"注册 async_write()\n↓\nasync_write() 立即返回\n↓\nmain 继续执行\n↓\n调用 io.run()\n↓\nAsio 等待异步发送完成\n↓\n调用发送完成回调\n↓\n没有其他异步任务\n↓\nio.run() 返回\n",[30,4473,4471],{"__ignoreMap":28},[55,4475,207],{"id":4476},"完整代码-2",[22,4478,4480],{"className":210,"code":4479,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n\n#include \u003Cfunctional>\n#include \u003Cprint>\n#include \u003Cstring>\n\nvoid on_write(\n    const boost::system::error_code& ec,\n    std::size_t bytes_transferred)\n{\n    if (ec)\n    {\n        std::println(\"on_write：发送失败：{}\", ec.message());\n        return;\n    }\n\n    std::println(\n        \"on_write：发送成功，字节数 = {}\",\n        bytes_transferred);\n}\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    \u002F\u002F io_context 是 Asio 的事件循环对象。\n    \u002F\u002F 异步任务需要由 io.run() 驱动。\n    boost::asio::io_context io;\n\n    boost::asio::serial_port serial(io);\n\n    boost::system::error_code ec;\n\n    std::println(\"main：准备打开串口 {}\", port_name);\n\n    serial.open(port_name, ec);\n\n    if (ec)\n    {\n        std::println(\"打开串口失败：{}\", ec.message());\n        return 1;\n    }\n\n    serial.set_option(\n        boost::asio::serial_port_base::baud_rate(115200));\n\n    serial.set_option(\n        boost::asio::serial_port_base::character_size(8));\n\n    serial.set_option(\n        boost::asio::serial_port_base::parity(\n            boost::asio::serial_port_base::parity::none));\n\n    serial.set_option(\n        boost::asio::serial_port_base::stop_bits(\n            boost::asio::serial_port_base::stop_bits::one));\n\n    serial.set_option(\n        boost::asio::serial_port_base::flow_control(\n            boost::asio::serial_port_base::flow_control::none));\n\n    std::string msg = \"hello async\\n\";\n\n    std::println(\"main：注册 async_write\");\n\n    boost::asio::async_write(\n        serial,\n        boost::asio::buffer(msg),\n        std::bind(\n            on_write,\n            std::placeholders::_1,\n            std::placeholders::_2));\n\n    std::println(\"main：async_write() 已返回\");\n\n    std::println(\"main：开始 io.run()\");\n\n    io.run();\n\n    std::println(\"main：io.run() 返回\");\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n",[30,4481,4482,4488,4494,4498,4505,4511,4517,4521,4531,4556,4569,4573,4579,4583,4602,4608,4612,4616,4626,4633,4638,4642,4646,4666,4670,4682,4686,4698,4702,4714,4718,4722,4727,4732,4742,4746,4760,4764,4774,4778,4792,4796,4804,4808,4814,4818,4836,4844,4848,4852,4860,4882,4886,4894,4916,4920,4928,4946,4964,4968,4976,4994,5012,5016,5024,5042,5060,5064,5081,5085,5100,5104,5118,5122,5136,5147,5152,5165,5176,5180,5195,5199,5214,5219,5229,5234,5250,5265,5270,5279],{"__ignoreMap":28},[70,4483,4484,4486],{"class":72,"line":73},[70,4485,220],{"class":219},[70,4487,223],{"class":80},[70,4489,4490,4492],{"class":72,"line":133},[70,4491,220],{"class":219},[70,4493,230],{"class":80},[70,4495,4496],{"class":72,"line":141},[70,4497,252],{"emptyLinePlaceholder":251},[70,4499,4500,4502],{"class":72,"line":240},[70,4501,220],{"class":219},[70,4503,4504],{"class":80}," \u003Cfunctional>\n",[70,4506,4507,4509],{"class":72,"line":248},[70,4508,220],{"class":219},[70,4510,237],{"class":80},[70,4512,4513,4515],{"class":72,"line":255},[70,4514,220],{"class":219},[70,4516,245],{"class":80},[70,4518,4519],{"class":72,"line":286},[70,4520,252],{"emptyLinePlaceholder":251},[70,4522,4523,4526,4529],{"class":72,"line":292},[70,4524,4525],{"class":219},"void",[70,4527,4528],{"class":76}," on_write",[70,4530,620],{"class":264},[70,4532,4533,4536,4538,4540,4542,4544,4547,4550,4553],{"class":72,"line":299},[70,4534,4535],{"class":219},"    const",[70,4537,787],{"class":76},[70,4539,386],{"class":264},[70,4541,426],{"class":76},[70,4543,386],{"class":264},[70,4545,4546],{"class":76},"error_code",[70,4548,4549],{"class":219},"&",[70,4551,4552],{"class":270}," ec",[70,4554,4555],{"class":264},",\n",[70,4557,4558,4560,4562,4564,4567],{"class":72,"line":317},[70,4559,302],{"class":76},[70,4561,386],{"class":264},[70,4563,779],{"class":219},[70,4565,4566],{"class":270}," bytes_transferred",[70,4568,337],{"class":264},[70,4570,4571],{"class":72,"line":322},[70,4572,289],{"class":264},[70,4574,4575,4577],{"class":72,"line":340},[70,4576,325],{"class":219},[70,4578,477],{"class":264},[70,4580,4581],{"class":72,"line":346},[70,4582,343],{"class":264},[70,4584,4585,4587,4589,4591,4593,4596,4598,4600],{"class":72,"line":363},[70,4586,488],{"class":76},[70,4588,386],{"class":264},[70,4590,444],{"class":76},[70,4592,265],{"class":264},[70,4594,4595],{"class":80},"\"on_write：发送失败：{}\"",[70,4597,500],{"class":264},[70,4599,503],{"class":76},[70,4601,506],{"class":264},[70,4603,4604,4606],{"class":72,"line":369},[70,4605,512],{"class":219},[70,4607,314],{"class":264},[70,4609,4610],{"class":72,"line":374},[70,4611,366],{"class":264},[70,4613,4614],{"class":72,"line":380},[70,4615,252],{"emptyLinePlaceholder":251},[70,4617,4618,4620,4622,4624],{"class":72,"line":395},[70,4619,302],{"class":76},[70,4621,386],{"class":264},[70,4623,444],{"class":76},[70,4625,620],{"class":264},[70,4627,4628,4631],{"class":72,"line":401},[70,4629,4630],{"class":80},"        \"on_write：发送成功，字节数 = {}\"",[70,4632,4555],{"class":264},[70,4634,4635],{"class":72,"line":419},[70,4636,4637],{"class":264},"        bytes_transferred);\n",[70,4639,4640],{"class":72,"line":432},[70,4641,920],{"class":264},[70,4643,4644],{"class":72,"line":437},[70,4645,252],{"emptyLinePlaceholder":251},[70,4647,4648,4650,4652,4654,4656,4658,4660,4662,4664],{"class":72,"line":455},[70,4649,258],{"class":219},[70,4651,261],{"class":76},[70,4653,265],{"class":264},[70,4655,258],{"class":219},[70,4657,271],{"class":270},[70,4659,274],{"class":264},[70,4661,277],{"class":219},[70,4663,280],{"class":270},[70,4665,283],{"class":264},[70,4667,4668],{"class":72,"line":460},[70,4669,289],{"class":264},[70,4671,4672,4674,4676,4678,4680],{"class":72,"line":472},[70,4673,302],{"class":76},[70,4675,305],{"class":264},[70,4677,308],{"class":219},[70,4679,311],{"class":80},[70,4681,314],{"class":264},[70,4683,4684],{"class":72,"line":480},[70,4685,252],{"emptyLinePlaceholder":251},[70,4687,4688,4690,4692,4694,4696],{"class":72,"line":485},[70,4689,325],{"class":219},[70,4691,328],{"class":264},[70,4693,331],{"class":219},[70,4695,334],{"class":124},[70,4697,337],{"class":264},[70,4699,4700],{"class":72,"line":509},[70,4701,343],{"class":264},[70,4703,4704,4706,4708,4710,4712],{"class":72,"line":520},[70,4705,349],{"class":264},[70,4707,308],{"class":219},[70,4709,354],{"class":264},[70,4711,357],{"class":124},[70,4713,360],{"class":264},[70,4715,4716],{"class":72,"line":525},[70,4717,366],{"class":264},[70,4719,4720],{"class":72,"line":530},[70,4721,252],{"emptyLinePlaceholder":251},[70,4723,4724],{"class":72,"line":565},[70,4725,4726],{"class":295},"    \u002F\u002F io_context 是 Asio 的事件循环对象。\n",[70,4728,4729],{"class":72,"line":596},[70,4730,4731],{"class":295},"    \u002F\u002F 异步任务需要由 io.run() 驱动。\n",[70,4733,4734,4736,4738,4740],{"class":72,"line":623},[70,4735,383],{"class":76},[70,4737,386],{"class":264},[70,4739,389],{"class":76},[70,4741,392],{"class":264},[70,4743,4744],{"class":72,"line":644},[70,4745,252],{"emptyLinePlaceholder":251},[70,4747,4748,4750,4752,4754,4756,4758],{"class":72,"line":670},[70,4749,383],{"class":76},[70,4751,386],{"class":264},[70,4753,389],{"class":76},[70,4755,410],{"class":264},[70,4757,413],{"class":76},[70,4759,416],{"class":264},[70,4761,4762],{"class":72,"line":690},[70,4763,252],{"emptyLinePlaceholder":251},[70,4765,4766,4768,4770,4772],{"class":72,"line":716},[70,4767,383],{"class":76},[70,4769,386],{"class":264},[70,4771,426],{"class":76},[70,4773,429],{"class":264},[70,4775,4776],{"class":72,"line":735},[70,4777,252],{"emptyLinePlaceholder":251},[70,4779,4780,4782,4784,4786,4788,4790],{"class":72,"line":740},[70,4781,302],{"class":76},[70,4783,386],{"class":264},[70,4785,444],{"class":76},[70,4787,265],{"class":264},[70,4789,449],{"class":80},[70,4791,452],{"class":264},[70,4793,4794],{"class":72,"line":761},[70,4795,252],{"emptyLinePlaceholder":251},[70,4797,4798,4800,4802],{"class":72,"line":766},[70,4799,463],{"class":264},[70,4801,466],{"class":76},[70,4803,469],{"class":264},[70,4805,4806],{"class":72,"line":772},[70,4807,252],{"emptyLinePlaceholder":251},[70,4809,4810,4812],{"class":72,"line":816},[70,4811,325],{"class":219},[70,4813,477],{"class":264},[70,4815,4816],{"class":72,"line":823},[70,4817,343],{"class":264},[70,4819,4820,4822,4824,4826,4828,4830,4832,4834],{"class":72,"line":828},[70,4821,488],{"class":76},[70,4823,386],{"class":264},[70,4825,444],{"class":76},[70,4827,265],{"class":264},[70,4829,497],{"class":80},[70,4831,500],{"class":264},[70,4833,503],{"class":76},[70,4835,506],{"class":264},[70,4837,4838,4840,4842],{"class":72,"line":848},[70,4839,512],{"class":219},[70,4841,515],{"class":124},[70,4843,314],{"class":264},[70,4845,4846],{"class":72,"line":857},[70,4847,366],{"class":264},[70,4849,4850],{"class":72,"line":862},[70,4851,252],{"emptyLinePlaceholder":251},[70,4853,4854,4856,4858],{"class":72,"line":867},[70,4855,463],{"class":264},[70,4857,535],{"class":76},[70,4859,620],{"class":264},[70,4861,4862,4864,4866,4868,4870,4872,4874,4876,4878,4880],{"class":72,"line":884},[70,4863,626],{"class":76},[70,4865,386],{"class":264},[70,4867,389],{"class":76},[70,4869,386],{"class":264},[70,4871,549],{"class":76},[70,4873,386],{"class":264},[70,4875,554],{"class":76},[70,4877,265],{"class":264},[70,4879,559],{"class":124},[70,4881,562],{"class":264},[70,4883,4884],{"class":72,"line":901},[70,4885,252],{"emptyLinePlaceholder":251},[70,4887,4888,4890,4892],{"class":72,"line":906},[70,4889,463],{"class":264},[70,4891,535],{"class":76},[70,4893,620],{"class":264},[70,4895,4896,4898,4900,4902,4904,4906,4908,4910,4912,4914],{"class":72,"line":917},[70,4897,626],{"class":76},[70,4899,386],{"class":264},[70,4901,389],{"class":76},[70,4903,386],{"class":264},[70,4905,549],{"class":76},[70,4907,386],{"class":264},[70,4909,586],{"class":76},[70,4911,265],{"class":264},[70,4913,591],{"class":124},[70,4915,562],{"class":264},[70,4917,4918],{"class":72,"line":1618},[70,4919,252],{"emptyLinePlaceholder":251},[70,4921,4922,4924,4926],{"class":72,"line":1640},[70,4923,463],{"class":264},[70,4925,535],{"class":76},[70,4927,620],{"class":264},[70,4929,4930,4932,4934,4936,4938,4940,4942,4944],{"class":72,"line":1645},[70,4931,626],{"class":76},[70,4933,386],{"class":264},[70,4935,389],{"class":76},[70,4937,386],{"class":264},[70,4939,549],{"class":76},[70,4941,386],{"class":264},[70,4943,617],{"class":76},[70,4945,620],{"class":264},[70,4947,4948,4950,4952,4954,4956,4958,4960,4962],{"class":72,"line":1661},[70,4949,1496],{"class":76},[70,4951,386],{"class":264},[70,4953,389],{"class":76},[70,4955,386],{"class":264},[70,4957,549],{"class":76},[70,4959,386],{"class":264},[70,4961,617],{"class":76},[70,4963,641],{"class":264},[70,4965,4966],{"class":72,"line":1666},[70,4967,252],{"emptyLinePlaceholder":251},[70,4969,4970,4972,4974],{"class":72,"line":1672},[70,4971,463],{"class":264},[70,4973,535],{"class":76},[70,4975,620],{"class":264},[70,4977,4978,4980,4982,4984,4986,4988,4990,4992],{"class":72,"line":1678},[70,4979,626],{"class":76},[70,4981,386],{"class":264},[70,4983,389],{"class":76},[70,4985,386],{"class":264},[70,4987,549],{"class":76},[70,4989,386],{"class":264},[70,4991,665],{"class":76},[70,4993,620],{"class":264},[70,4995,4996,4998,5000,5002,5004,5006,5008,5010],{"class":72,"line":1692},[70,4997,1496],{"class":76},[70,4999,386],{"class":264},[70,5001,389],{"class":76},[70,5003,386],{"class":264},[70,5005,549],{"class":76},[70,5007,386],{"class":264},[70,5009,665],{"class":76},[70,5011,687],{"class":264},[70,5013,5014],{"class":72,"line":1708},[70,5015,252],{"emptyLinePlaceholder":251},[70,5017,5018,5020,5022],{"class":72,"line":1714},[70,5019,463],{"class":264},[70,5021,535],{"class":76},[70,5023,620],{"class":264},[70,5025,5026,5028,5030,5032,5034,5036,5038,5040],{"class":72,"line":1730},[70,5027,626],{"class":76},[70,5029,386],{"class":264},[70,5031,389],{"class":76},[70,5033,386],{"class":264},[70,5035,549],{"class":76},[70,5037,386],{"class":264},[70,5039,711],{"class":76},[70,5041,620],{"class":264},[70,5043,5044,5046,5048,5050,5052,5054,5056,5058],{"class":72,"line":1736},[70,5045,1496],{"class":76},[70,5047,386],{"class":264},[70,5049,389],{"class":76},[70,5051,386],{"class":264},[70,5053,549],{"class":76},[70,5055,386],{"class":264},[70,5057,711],{"class":76},[70,5059,641],{"class":264},[70,5061,5062],{"class":72,"line":1741},[70,5063,252],{"emptyLinePlaceholder":251},[70,5065,5066,5068,5070,5072,5075,5077,5079],{"class":72,"line":1748},[70,5067,302],{"class":76},[70,5069,745],{"class":264},[70,5071,308],{"class":219},[70,5073,5074],{"class":80}," \"hello async",[70,5076,753],{"class":124},[70,5078,756],{"class":80},[70,5080,314],{"class":264},[70,5082,5083],{"class":72,"line":1753},[70,5084,252],{"emptyLinePlaceholder":251},[70,5086,5087,5089,5091,5093,5095,5098],{"class":72,"line":1773},[70,5088,302],{"class":76},[70,5090,386],{"class":264},[70,5092,444],{"class":76},[70,5094,265],{"class":264},[70,5096,5097],{"class":80},"\"main：注册 async_write\"",[70,5099,898],{"class":264},[70,5101,5102],{"class":72,"line":1782},[70,5103,252],{"emptyLinePlaceholder":251},[70,5105,5106,5108,5110,5112,5114,5116],{"class":72,"line":1787},[70,5107,383],{"class":76},[70,5109,386],{"class":264},[70,5111,389],{"class":76},[70,5113,386],{"class":264},[70,5115,4446],{"class":76},[70,5117,620],{"class":264},[70,5119,5120],{"class":72,"line":1792},[70,5121,3025],{"class":264},[70,5123,5124,5126,5128,5130,5132,5134],{"class":72,"line":1798},[70,5125,626],{"class":76},[70,5127,386],{"class":264},[70,5129,389],{"class":76},[70,5131,386],{"class":264},[70,5133,810],{"class":76},[70,5135,3662],{"class":264},[70,5137,5138,5140,5142,5145],{"class":72,"line":1818},[70,5139,488],{"class":76},[70,5141,386],{"class":264},[70,5143,5144],{"class":76},"bind",[70,5146,620],{"class":264},[70,5148,5149],{"class":72,"line":1823},[70,5150,5151],{"class":264},"            on_write,\n",[70,5153,5154,5157,5159,5162],{"class":72,"line":1839},[70,5155,5156],{"class":76},"            std",[70,5158,386],{"class":264},[70,5160,5161],{"class":76},"placeholders",[70,5163,5164],{"class":264},"::_1,\n",[70,5166,5167,5169,5171,5173],{"class":72,"line":1856},[70,5168,5156],{"class":76},[70,5170,386],{"class":264},[70,5172,5161],{"class":76},[70,5174,5175],{"class":264},"::_2));\n",[70,5177,5178],{"class":72,"line":1861},[70,5179,252],{"emptyLinePlaceholder":251},[70,5181,5182,5184,5186,5188,5190,5193],{"class":72,"line":1876},[70,5183,302],{"class":76},[70,5185,386],{"class":264},[70,5187,444],{"class":76},[70,5189,265],{"class":264},[70,5191,5192],{"class":80},"\"main：async_write() 已返回\"",[70,5194,898],{"class":264},[70,5196,5197],{"class":72,"line":1881},[70,5198,252],{"emptyLinePlaceholder":251},[70,5200,5201,5203,5205,5207,5209,5212],{"class":72,"line":1890},[70,5202,302],{"class":76},[70,5204,386],{"class":264},[70,5206,444],{"class":76},[70,5208,265],{"class":264},[70,5210,5211],{"class":80},"\"main：开始 io.run()\"",[70,5213,898],{"class":264},[70,5215,5217],{"class":72,"line":5216},83,[70,5218,252],{"emptyLinePlaceholder":251},[70,5220,5222,5225,5227],{"class":72,"line":5221},84,[70,5223,5224],{"class":264},"    io.",[70,5226,2237],{"class":76},[70,5228,2240],{"class":264},[70,5230,5232],{"class":72,"line":5231},85,[70,5233,252],{"emptyLinePlaceholder":251},[70,5235,5237,5239,5241,5243,5245,5248],{"class":72,"line":5236},86,[70,5238,302],{"class":76},[70,5240,386],{"class":264},[70,5242,444],{"class":76},[70,5244,265],{"class":264},[70,5246,5247],{"class":80},"\"main：io.run() 返回\"",[70,5249,898],{"class":264},[70,5251,5253,5255,5257,5259,5261,5263],{"class":72,"line":5252},87,[70,5254,302],{"class":76},[70,5256,386],{"class":264},[70,5258,444],{"class":76},[70,5260,265],{"class":264},[70,5262,895],{"class":80},[70,5264,898],{"class":264},[70,5266,5268],{"class":72,"line":5267},88,[70,5269,252],{"emptyLinePlaceholder":251},[70,5271,5273,5275,5277],{"class":72,"line":5272},89,[70,5274,909],{"class":219},[70,5276,912],{"class":124},[70,5278,314],{"class":264},[70,5280,5282],{"class":72,"line":5281},90,[70,5283,920],{"class":264},[55,5285,930],{"id":5286},"编译运行-2",[15,5288,933],{},[22,5290,5291],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,5292,5293,5303,5309],{"__ignoreMap":28},[70,5294,5295,5297,5299,5301],{"class":72,"line":73},[70,5296,52],{"class":76},[70,5298,125],{"class":124},[70,5300,125],{"class":124},[70,5302,130],{"class":124},[70,5304,5305,5307],{"class":72,"line":133},[70,5306,136],{"class":80},[70,5308,130],{"class":124},[70,5310,5311],{"class":72,"line":141},[70,5312,144],{"class":80},[15,5314,1929],{},[22,5316,5318],{"className":5317,"code":1933,"language":27,"meta":28},[25],[30,5319,1933],{"__ignoreMap":28},[15,5321,5322],{},"终端 2：监听串口另一端。",[22,5324,5325],{"className":64,"code":963,"language":66,"meta":28,"style":28},[30,5326,5327],{"__ignoreMap":28},[70,5328,5329,5331],{"class":72,"line":73},[70,5330,970],{"class":76},[70,5332,973],{"class":80},[15,5334,976],{},[55,5336,982],{"id":5337},"运行输出与时间顺序-2",[15,5339,5340],{},"程序输出类似：",[22,5342,5345],{"className":5343,"code":5344,"language":27,"meta":28},[25],"main：准备打开串口 \u002Fdev\u002Fpts\u002F3\nmain：注册 async_write\nmain：async_write() 已返回\nmain：开始 io.run()\non_write：发送成功，字节数 = 12\nmain：io.run() 返回\nmain：程序结束\n",[30,5346,5344],{"__ignoreMap":28},[15,5348,1000],{},[22,5350,5352],{"className":5351,"code":4457,"language":27,"meta":28},[25],[30,5353,4457],{"__ignoreMap":28},[15,5355,5356],{},"这里最值得注意的是：",[22,5358,5361],{"className":5359,"code":5360,"language":27,"meta":28},[25],"main：注册 async_write\nmain：async_write() 已返回\n",[30,5362,5360],{"__ignoreMap":28},[15,5364,5365],{},"会先出现。",[15,5367,5368],{},"这说明：",[22,5370,5372],{"className":210,"code":5371,"language":212,"meta":28,"style":28},"boost::asio::async_write(...)\n",[30,5373,5374],{"__ignoreMap":28},[70,5375,5376,5378,5380,5382,5384,5386],{"class":72,"line":73},[70,5377,540],{"class":76},[70,5379,386],{"class":264},[70,5381,389],{"class":76},[70,5383,386],{"class":264},[70,5385,4446],{"class":76},[70,5387,3449],{"class":264},[15,5389,5390],{},"本身不会等数据发送完成。",[15,5392,5393],{},"它做的是：",[22,5395,5398],{"className":5396,"code":5397,"language":27,"meta":28},[25],"登记一个异步发送任务\n↓\n告诉 Asio：\n\n“把这些数据发出去，\n发完以后调用 on_write()”\n↓\nasync_write() 立即返回\n",[30,5399,5397],{"__ignoreMap":28},[15,5401,5402],{},"真正等待和处理异步事件的是：",[22,5404,5405],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,5406,5407],{"__ignoreMap":28},[70,5408,5409,5411,5413],{"class":72,"line":73},[70,5410,2234],{"class":264},[70,5412,2237],{"class":76},[70,5414,2240],{"class":264},[40,5416],{},[55,5418,1016],{"id":5419},"本示例需要注意的点-2",[15,5421,5422],{},"同步发送：",[22,5424,5425],{"className":210,"code":3707,"language":212,"meta":28,"style":28},[30,5426,5427],{"__ignoreMap":28},[70,5428,5429,5431,5433,5435,5437,5439],{"class":72,"line":73},[70,5430,540],{"class":76},[70,5432,386],{"class":264},[70,5434,389],{"class":76},[70,5436,386],{"class":264},[70,5438,796],{"class":76},[70,5440,3449],{"class":264},[15,5442,5443],{},"流程是：",[22,5445,5448],{"className":5446,"code":5447,"language":27,"meta":28},[25],"调用 write()\n↓\n当前线程阻塞\n↓\n整个 buffer 发送完成\n↓\nwrite() 返回\n",[30,5449,5447],{"__ignoreMap":28},[15,5451,5452],{},"异步发送：",[22,5454,5455],{"className":210,"code":5371,"language":212,"meta":28,"style":28},[30,5456,5457],{"__ignoreMap":28},[70,5458,5459,5461,5463,5465,5467,5469],{"class":72,"line":73},[70,5460,540],{"class":76},[70,5462,386],{"class":264},[70,5464,389],{"class":76},[70,5466,386],{"class":264},[70,5468,4446],{"class":76},[70,5470,3449],{"class":264},[15,5472,5443],{},[22,5474,5477],{"className":5475,"code":5476,"language":27,"meta":28},[25],"调用 async_write()\n↓\n登记异步发送任务\n↓\n立即返回\n↓\nio.run() 驱动任务\n↓\n发送完成\n↓\n调用回调\n",[30,5478,5476],{"__ignoreMap":28},[15,5480,5481],{},"所以异步接口通常必须配合：",[22,5483,5484],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,5485,5486],{"__ignoreMap":28},[70,5487,5488,5490,5492],{"class":72,"line":73},[70,5489,2234],{"class":264},[70,5491,2237],{"class":76},[70,5493,2240],{"class":264},[15,5495,5496],{},"如果本例删掉：",[22,5498,5499],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,5500,5501],{"__ignoreMap":28},[70,5502,5503,5505,5507],{"class":72,"line":73},[70,5504,2234],{"class":264},[70,5506,2237],{"class":76},[70,5508,2240],{"class":264},[15,5510,5511],{},"那么程序很快就会走到：",[22,5513,5515],{"className":210,"code":5514,"language":212,"meta":28,"style":28},"return 0;\n",[30,5516,5517],{"__ignoreMap":28},[70,5518,5519,5522,5524],{"class":72,"line":73},[70,5520,5521],{"class":219},"return",[70,5523,912],{"class":124},[70,5525,314],{"class":264},[15,5527,5528],{},"异步任务将得不到正常的事件循环驱动。",[40,5530],{},[55,5532,5534,5537],{"id":5533},"async_write-的回调参数",[30,5535,5536],{},"async_write()"," 的回调参数",[15,5539,5540],{},"本例回调函数：",[22,5542,5544],{"className":210,"code":5543,"language":212,"meta":28,"style":28},"void on_write(\n    const boost::system::error_code& ec,\n    std::size_t bytes_transferred)\n",[30,5545,5546,5554,5574],{"__ignoreMap":28},[70,5547,5548,5550,5552],{"class":72,"line":73},[70,5549,4525],{"class":219},[70,5551,4528],{"class":76},[70,5553,620],{"class":264},[70,5555,5556,5558,5560,5562,5564,5566,5568,5570,5572],{"class":72,"line":133},[70,5557,4535],{"class":219},[70,5559,787],{"class":76},[70,5561,386],{"class":264},[70,5563,426],{"class":76},[70,5565,386],{"class":264},[70,5567,4546],{"class":76},[70,5569,4549],{"class":219},[70,5571,4552],{"class":270},[70,5573,4555],{"class":264},[70,5575,5576,5578,5580,5582,5584],{"class":72,"line":141},[70,5577,302],{"class":76},[70,5579,386],{"class":264},[70,5581,779],{"class":219},[70,5583,4566],{"class":270},[70,5585,337],{"class":264},[15,5587,5588],{},"有两个参数。",[15,5590,5591],{},"第一个：",[22,5593,5595],{"className":210,"code":5594,"language":212,"meta":28,"style":28},"const boost::system::error_code& ec\n",[30,5596,5597],{"__ignoreMap":28},[70,5598,5599,5602,5604,5606,5608,5611,5613],{"class":72,"line":73},[70,5600,5601],{"class":219},"const",[70,5603,787],{"class":76},[70,5605,386],{"class":264},[70,5607,426],{"class":76},[70,5609,5610],{"class":264},"::error_code",[70,5612,4549],{"class":219},[70,5614,5615],{"class":264}," ec\n",[15,5617,5618],{},"表示异步操作有没有发生错误。",[15,5620,5621],{},"第二个：",[22,5623,5625],{"className":210,"code":5624,"language":212,"meta":28,"style":28},"std::size_t bytes_transferred\n",[30,5626,5627],{"__ignoreMap":28},[70,5628,5629,5631,5633,5635],{"class":72,"line":73},[70,5630,2058],{"class":76},[70,5632,386],{"class":264},[70,5634,779],{"class":219},[70,5636,5637],{"class":264}," bytes_transferred\n",[15,5639,5640],{},"表示实际完成传输的字节数。",[15,5642,5643],{},"因此绑定时：",[22,5645,5647],{"className":210,"code":5646,"language":212,"meta":28,"style":28},"std::bind(\n    on_write,\n    std::placeholders::_1,\n    std::placeholders::_2)\n",[30,5648,5649,5659,5664,5674],{"__ignoreMap":28},[70,5650,5651,5653,5655,5657],{"class":72,"line":73},[70,5652,2058],{"class":76},[70,5654,386],{"class":264},[70,5656,5144],{"class":76},[70,5658,620],{"class":264},[70,5660,5661],{"class":72,"line":133},[70,5662,5663],{"class":264},"    on_write,\n",[70,5665,5666,5668,5670,5672],{"class":72,"line":141},[70,5667,302],{"class":76},[70,5669,386],{"class":264},[70,5671,5161],{"class":76},[70,5673,5164],{"class":264},[70,5675,5676,5678,5680,5682],{"class":72,"line":240},[70,5677,302],{"class":76},[70,5679,386],{"class":264},[70,5681,5161],{"class":76},[70,5683,5684],{"class":264},"::_2)\n",[15,5686,3047],{},[22,5688,5691],{"className":5689,"code":5690,"language":27,"meta":28},[25],"_1\n→ ec\n\n_2\n→ bytes_transferred\n",[30,5692,5690],{"__ignoreMap":28},[40,5694],{},[55,5696,3949,5698,5700],{"id":5697},"为什么-msg-不能过早销毁",[30,5699,1806],{}," 不能过早销毁？",[15,5702,5703],{},"这里：",[22,5705,5707],{"className":210,"code":5706,"language":212,"meta":28,"style":28},"std::string msg = \"hello async\\n\";\n",[30,5708,5709],{"__ignoreMap":28},[70,5710,5711,5713,5715,5717,5719,5721,5723],{"class":72,"line":73},[70,5712,2058],{"class":76},[70,5714,745],{"class":264},[70,5716,308],{"class":219},[70,5718,5074],{"class":80},[70,5720,753],{"class":124},[70,5722,756],{"class":80},[70,5724,314],{"class":264},[15,5726,5727],{},"然后：",[22,5729,5731],{"className":210,"code":5730,"language":212,"meta":28,"style":28},"boost::asio::async_write(\n    serial,\n    boost::asio::buffer(msg),\n    ...);\n",[30,5732,5733,5747,5751,5765],{"__ignoreMap":28},[70,5734,5735,5737,5739,5741,5743,5745],{"class":72,"line":73},[70,5736,540],{"class":76},[70,5738,386],{"class":264},[70,5740,389],{"class":76},[70,5742,386],{"class":264},[70,5744,4446],{"class":76},[70,5746,620],{"class":264},[70,5748,5749],{"class":72,"line":133},[70,5750,2026],{"class":264},[70,5752,5753,5755,5757,5759,5761,5763],{"class":72,"line":141},[70,5754,383],{"class":76},[70,5756,386],{"class":264},[70,5758,389],{"class":76},[70,5760,386],{"class":264},[70,5762,810],{"class":76},[70,5764,3662],{"class":264},[70,5766,5767],{"class":72,"line":240},[70,5768,5769],{"class":264},"    ...);\n",[15,5771,5772,5775,5776,5778],{},[30,5773,5774],{},"boost::asio::buffer(msg)"," 并不会复制 ",[30,5777,1806],{}," 的数据。",[15,5780,5781],{},"它只是描述：",[22,5783,5786],{"className":5784,"code":5785,"language":27,"meta":28},[25],"msg 的内存地址\n+\nmsg 的长度\n",[30,5787,5785],{"__ignoreMap":28},[15,5789,5790],{},"因此在异步写完成之前：",[22,5792,5795],{"className":5793,"code":5794,"language":27,"meta":28},[25],"msg 必须仍然存在\n",[30,5796,5794],{"__ignoreMap":28},[15,5798,5799],{},"本例没有问题，因为：",[22,5801,5804],{"className":5802,"code":5803,"language":27,"meta":28},[25],"msg 是 main() 的局部变量\n↓\nasync_write()\n↓\nio.run()\n↓\n异步写完成\n↓\nio.run() 返回\n↓\nmain() 最后才结束\n",[30,5805,5803],{"__ignoreMap":28},[15,5807,5808],{},"所以异步发送期间：",[22,5810,5812],{"className":210,"code":5811,"language":212,"meta":28,"style":28},"msg\n",[30,5813,5814],{"__ignoreMap":28},[70,5815,5816],{"class":72,"line":73},[70,5817,5811],{"class":264},[15,5819,5820],{},"一直存在。",[15,5822,5823],{},"不能写成这种结构：",[22,5825,5827],{"className":210,"code":5826,"language":212,"meta":28,"style":28},"void send(boost::asio::serial_port& serial)\n{\n    std::string msg = \"hello\\n\";\n\n    boost::asio::async_write(\n        serial,\n        boost::asio::buffer(msg),\n        handler);\n}\n",[30,5828,5829,5856,5860,5877,5881,5895,5899,5913,5918],{"__ignoreMap":28},[70,5830,5831,5833,5836,5838,5840,5842,5844,5846,5849,5851,5854],{"class":72,"line":73},[70,5832,4525],{"class":219},[70,5834,5835],{"class":76}," send",[70,5837,265],{"class":264},[70,5839,540],{"class":76},[70,5841,386],{"class":264},[70,5843,389],{"class":76},[70,5845,386],{"class":264},[70,5847,5848],{"class":76},"serial_port",[70,5850,4549],{"class":219},[70,5852,5853],{"class":270}," serial",[70,5855,337],{"class":264},[70,5857,5858],{"class":72,"line":133},[70,5859,289],{"class":264},[70,5861,5862,5864,5866,5868,5871,5873,5875],{"class":72,"line":141},[70,5863,302],{"class":76},[70,5865,745],{"class":264},[70,5867,308],{"class":219},[70,5869,5870],{"class":80}," \"hello",[70,5872,753],{"class":124},[70,5874,756],{"class":80},[70,5876,314],{"class":264},[70,5878,5879],{"class":72,"line":240},[70,5880,252],{"emptyLinePlaceholder":251},[70,5882,5883,5885,5887,5889,5891,5893],{"class":72,"line":248},[70,5884,383],{"class":76},[70,5886,386],{"class":264},[70,5888,389],{"class":76},[70,5890,386],{"class":264},[70,5892,4446],{"class":76},[70,5894,620],{"class":264},[70,5896,5897],{"class":72,"line":255},[70,5898,3025],{"class":264},[70,5900,5901,5903,5905,5907,5909,5911],{"class":72,"line":286},[70,5902,626],{"class":76},[70,5904,386],{"class":264},[70,5906,389],{"class":76},[70,5908,386],{"class":264},[70,5910,810],{"class":76},[70,5912,3662],{"class":264},[70,5914,5915],{"class":72,"line":292},[70,5916,5917],{"class":264},"        handler);\n",[70,5919,5920],{"class":72,"line":299},[70,5921,920],{"class":264},[15,5923,5924],{},"然后立刻让：",[22,5926,5928],{"className":210,"code":5927,"language":212,"meta":28,"style":28},"send()\n",[30,5929,5930],{"__ignoreMap":28},[70,5931,5932,5935],{"class":72,"line":73},[70,5933,5934],{"class":76},"send",[70,5936,3162],{"class":264},[15,5938,5939],{},"返回。",[15,5941,2048],{},[22,5943,5946],{"className":5944,"code":5945,"language":27,"meta":28},[25],"send() 返回\n↓\nmsg 被销毁\n↓\n异步写可能还没有完成\n↓\nbuffer 指向的内存失效\n",[30,5947,5945],{"__ignoreMap":28},[40,5949],{},[55,5951,5953,5956],{"id":5952},"boostasioasync_write-说明",[30,5954,5955],{},"boost::asio::async_write()"," 说明",[22,5958,5960],{"className":210,"code":5959,"language":212,"meta":28,"style":28},"boost::asio::async_write(\n    serial,\n    boost::asio::buffer(msg),\n    handler);\n",[30,5961,5962,5976,5980,5994],{"__ignoreMap":28},[70,5963,5964,5966,5968,5970,5972,5974],{"class":72,"line":73},[70,5965,540],{"class":76},[70,5967,386],{"class":264},[70,5969,389],{"class":76},[70,5971,386],{"class":264},[70,5973,4446],{"class":76},[70,5975,620],{"class":264},[70,5977,5978],{"class":72,"line":133},[70,5979,2026],{"class":264},[70,5981,5982,5984,5986,5988,5990,5992],{"class":72,"line":141},[70,5983,383],{"class":76},[70,5985,386],{"class":264},[70,5987,389],{"class":76},[70,5989,386],{"class":264},[70,5991,810],{"class":76},[70,5993,3662],{"class":264},[70,5995,5996],{"class":72,"line":240},[70,5997,5998],{"class":264},"    handler);\n",[15,6000,6001],{},"作用：",[12,6003,6004],{},[15,6005,6006],{},"异步发送整个指定 buffer。",[15,6008,6009],{},"它不会等待发送完成。",[15,6011,6012],{},"而是：",[22,6014,6017],{"className":6015,"code":6016,"language":27,"meta":28},[25],"注册任务\n↓\n立即返回\n↓\nio.run() 驱动\n↓\n整个 buffer 发送完成\n↓\n执行 handler\n",[30,6018,6016],{"__ignoreMap":28},[15,6020,3227],{},[12,6022,6023],{},[15,6024,6025,6027],{},[30,6026,5536],{}," = “我要异步把整个 buffer 发完，完成以后调用回调”。",[40,6029],{},[43,6031,6033,6034,6036],{"id":6032},"示例-4普通-main-里异步读取串口数据","示例 4：普通 ",[30,6035,182],{}," 里异步读取串口数据",[55,6038,186],{"id":6039},"程序目标-3",[15,6041,6042],{},"前面的示例 2 使用：",[22,6044,6045],{"className":210,"code":4281,"language":212,"meta":28,"style":28},[30,6046,6047],{"__ignoreMap":28},[70,6048,6049,6051,6053,6055,6057,6059],{"class":72,"line":73},[70,6050,540],{"class":76},[70,6052,386],{"class":264},[70,6054,389],{"class":76},[70,6056,386],{"class":264},[70,6058,1703],{"class":76},[70,6060,3162],{"class":264},[15,6062,6063],{},"同步读取 11 个字节。",[15,6065,6066],{},"这一节把它改成：",[22,6068,6070],{"className":210,"code":6069,"language":212,"meta":28,"style":28},"boost::asio::async_read()\n",[30,6071,6072],{"__ignoreMap":28},[70,6073,6074,6076,6078,6080,6082,6085],{"class":72,"line":73},[70,6075,540],{"class":76},[70,6077,386],{"class":264},[70,6079,389],{"class":76},[70,6081,386],{"class":264},[70,6083,6084],{"class":76},"async_read",[70,6086,3162],{"class":264},[15,6088,6089],{},"异步读取。",[15,6091,6092,6093,6095],{},"程序打开 ",[30,6094,168],{},"，然后注册一个：",[22,6097,6100],{"className":6098,"code":6099,"language":27,"meta":28},[25],"异步读取 11 字节\n",[30,6101,6099],{"__ignoreMap":28},[15,6103,6104],{},"的任务。",[15,6106,6107],{},"另一个终端发送：",[22,6109,6111],{"className":6110,"code":1136,"language":27,"meta":28},[25],[30,6112,1136],{"__ignoreMap":28},[15,6114,1141],{},[15,6116,6117],{},"读取完成后，Asio 调用回调函数。",[15,6119,6120],{},"执行流程：",[22,6122,6125],{"className":6123,"code":6124,"language":27,"meta":28},[25],"注册 async_read()\n↓\nasync_read() 立即返回\n↓\nmain 调用 io.run()\n↓\n等待数据\n↓\n累计收到 11 字节\n↓\n调用 on_read()\n↓\n没有其他异步任务\n↓\nio.run() 返回\n",[30,6126,6124],{"__ignoreMap":28},[55,6128,207],{"id":6129},"完整代码-3",[22,6131,6133],{"className":210,"code":6132,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Carray>\n#include \u003Cfunctional>\n#include \u003Cprint>\n#include \u003Cstring>\n\nvoid on_read(\n    const boost::system::error_code& ec,\n    std::size_t bytes_transferred,\n    std::array\u003Cchar, 11>* buffer)\n{\n    if (ec)\n    {\n        std::println(\"on_read：读取失败：{}\", ec.message());\n        return;\n    }\n\n    std::string msg(\n        buffer->data(),\n        bytes_transferred);\n\n    std::println(\n        \"on_read：读取成功，字节数 = {}\",\n        bytes_transferred);\n\n    std::println(\n        \"on_read：收到的数据 = {}\",\n        msg);\n}\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    boost::asio::serial_port serial(io);\n\n    boost::system::error_code ec;\n\n    std::println(\"main：准备打开串口 {}\", port_name);\n\n    serial.open(port_name, ec);\n\n    if (ec)\n    {\n        std::println(\"打开串口失败：{}\", ec.message());\n        return 1;\n    }\n\n    serial.set_option(\n        boost::asio::serial_port_base::baud_rate(115200));\n\n    serial.set_option(\n        boost::asio::serial_port_base::character_size(8));\n\n    serial.set_option(\n        boost::asio::serial_port_base::parity(\n            boost::asio::serial_port_base::parity::none));\n\n    serial.set_option(\n        boost::asio::serial_port_base::stop_bits(\n            boost::asio::serial_port_base::stop_bits::one));\n\n    serial.set_option(\n        boost::asio::serial_port_base::flow_control(\n            boost::asio::serial_port_base::flow_control::none));\n\n    std::array\u003Cchar, 11> buffer{};\n\n    std::println(\"main：注册 async_read，等待接收 11 个字节\");\n\n    boost::asio::async_read(\n        serial,\n        boost::asio::buffer(buffer),\n        std::bind(\n            on_read,\n            std::placeholders::_1,\n            std::placeholders::_2,\n            &buffer));\n\n    std::println(\"main：async_read() 已返回\");\n\n    std::println(\"main：开始 io.run()\");\n\n    io.run();\n\n    std::println(\"main：io.run() 返回\");\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n",[30,6134,6135,6141,6147,6153,6159,6165,6171,6175,6184,6204,6216,6244,6248,6254,6258,6277,6283,6287,6291,6301,6311,6315,6319,6329,6336,6340,6344,6354,6361,6366,6370,6374,6394,6398,6410,6414,6426,6430,6442,6446,6450,6460,6464,6478,6482,6492,6496,6510,6514,6522,6526,6532,6536,6554,6562,6566,6570,6578,6600,6604,6612,6634,6638,6646,6664,6682,6686,6694,6712,6730,6734,6742,6760,6778,6782,6798,6802,6817,6821,6835,6839,6853,6863,6868,6878,6889,6897,6901,6916,6920,6934,6939,6948,6953,6968,6983,6988,6997],{"__ignoreMap":28},[70,6136,6137,6139],{"class":72,"line":73},[70,6138,220],{"class":219},[70,6140,223],{"class":80},[70,6142,6143,6145],{"class":72,"line":133},[70,6144,220],{"class":219},[70,6146,230],{"class":80},[70,6148,6149,6151],{"class":72,"line":141},[70,6150,220],{"class":219},[70,6152,1172],{"class":80},[70,6154,6155,6157],{"class":72,"line":240},[70,6156,220],{"class":219},[70,6158,4504],{"class":80},[70,6160,6161,6163],{"class":72,"line":248},[70,6162,220],{"class":219},[70,6164,237],{"class":80},[70,6166,6167,6169],{"class":72,"line":255},[70,6168,220],{"class":219},[70,6170,245],{"class":80},[70,6172,6173],{"class":72,"line":286},[70,6174,252],{"emptyLinePlaceholder":251},[70,6176,6177,6179,6182],{"class":72,"line":292},[70,6178,4525],{"class":219},[70,6180,6181],{"class":76}," on_read",[70,6183,620],{"class":264},[70,6185,6186,6188,6190,6192,6194,6196,6198,6200,6202],{"class":72,"line":299},[70,6187,4535],{"class":219},[70,6189,787],{"class":76},[70,6191,386],{"class":264},[70,6193,426],{"class":76},[70,6195,386],{"class":264},[70,6197,4546],{"class":76},[70,6199,4549],{"class":219},[70,6201,4552],{"class":270},[70,6203,4555],{"class":264},[70,6205,6206,6208,6210,6212,6214],{"class":72,"line":317},[70,6207,302],{"class":76},[70,6209,386],{"class":264},[70,6211,779],{"class":219},[70,6213,4566],{"class":270},[70,6215,4555],{"class":264},[70,6217,6218,6220,6222,6224,6227,6230,6232,6234,6236,6239,6242],{"class":72,"line":322},[70,6219,302],{"class":76},[70,6221,386],{"class":264},[70,6223,2247],{"class":76},[70,6225,6226],{"class":264},"\u003C",[70,6228,6229],{"class":219},"char",[70,6231,274],{"class":264},[70,6233,1631],{"class":124},[70,6235,1634],{"class":264},[70,6237,6238],{"class":219},"*",[70,6240,6241],{"class":270}," buffer",[70,6243,337],{"class":264},[70,6245,6246],{"class":72,"line":340},[70,6247,289],{"class":264},[70,6249,6250,6252],{"class":72,"line":346},[70,6251,325],{"class":219},[70,6253,477],{"class":264},[70,6255,6256],{"class":72,"line":363},[70,6257,343],{"class":264},[70,6259,6260,6262,6264,6266,6268,6271,6273,6275],{"class":72,"line":369},[70,6261,488],{"class":76},[70,6263,386],{"class":264},[70,6265,444],{"class":76},[70,6267,265],{"class":264},[70,6269,6270],{"class":80},"\"on_read：读取失败：{}\"",[70,6272,500],{"class":264},[70,6274,503],{"class":76},[70,6276,506],{"class":264},[70,6278,6279,6281],{"class":72,"line":374},[70,6280,512],{"class":219},[70,6282,314],{"class":264},[70,6284,6285],{"class":72,"line":380},[70,6286,366],{"class":264},[70,6288,6289],{"class":72,"line":395},[70,6290,252],{"emptyLinePlaceholder":251},[70,6292,6293,6295,6297,6299],{"class":72,"line":401},[70,6294,302],{"class":76},[70,6296,1803],{"class":264},[70,6298,1806],{"class":76},[70,6300,620],{"class":264},[70,6302,6303,6306,6308],{"class":72,"line":419},[70,6304,6305],{"class":264},"        buffer->",[70,6307,1812],{"class":76},[70,6309,6310],{"class":264},"(),\n",[70,6312,6313],{"class":72,"line":432},[70,6314,4637],{"class":264},[70,6316,6317],{"class":72,"line":437},[70,6318,252],{"emptyLinePlaceholder":251},[70,6320,6321,6323,6325,6327],{"class":72,"line":455},[70,6322,302],{"class":76},[70,6324,386],{"class":264},[70,6326,444],{"class":76},[70,6328,620],{"class":264},[70,6330,6331,6334],{"class":72,"line":460},[70,6332,6333],{"class":80},"        \"on_read：读取成功，字节数 = {}\"",[70,6335,4555],{"class":264},[70,6337,6338],{"class":72,"line":472},[70,6339,4637],{"class":264},[70,6341,6342],{"class":72,"line":480},[70,6343,252],{"emptyLinePlaceholder":251},[70,6345,6346,6348,6350,6352],{"class":72,"line":485},[70,6347,302],{"class":76},[70,6349,386],{"class":264},[70,6351,444],{"class":76},[70,6353,620],{"class":264},[70,6355,6356,6359],{"class":72,"line":509},[70,6357,6358],{"class":80},"        \"on_read：收到的数据 = {}\"",[70,6360,4555],{"class":264},[70,6362,6363],{"class":72,"line":520},[70,6364,6365],{"class":264},"        msg);\n",[70,6367,6368],{"class":72,"line":525},[70,6369,920],{"class":264},[70,6371,6372],{"class":72,"line":530},[70,6373,252],{"emptyLinePlaceholder":251},[70,6375,6376,6378,6380,6382,6384,6386,6388,6390,6392],{"class":72,"line":565},[70,6377,258],{"class":219},[70,6379,261],{"class":76},[70,6381,265],{"class":264},[70,6383,258],{"class":219},[70,6385,271],{"class":270},[70,6387,274],{"class":264},[70,6389,277],{"class":219},[70,6391,280],{"class":270},[70,6393,283],{"class":264},[70,6395,6396],{"class":72,"line":596},[70,6397,289],{"class":264},[70,6399,6400,6402,6404,6406,6408],{"class":72,"line":623},[70,6401,302],{"class":76},[70,6403,305],{"class":264},[70,6405,308],{"class":219},[70,6407,311],{"class":80},[70,6409,314],{"class":264},[70,6411,6412],{"class":72,"line":644},[70,6413,252],{"emptyLinePlaceholder":251},[70,6415,6416,6418,6420,6422,6424],{"class":72,"line":670},[70,6417,325],{"class":219},[70,6419,328],{"class":264},[70,6421,331],{"class":219},[70,6423,334],{"class":124},[70,6425,337],{"class":264},[70,6427,6428],{"class":72,"line":690},[70,6429,343],{"class":264},[70,6431,6432,6434,6436,6438,6440],{"class":72,"line":716},[70,6433,349],{"class":264},[70,6435,308],{"class":219},[70,6437,354],{"class":264},[70,6439,357],{"class":124},[70,6441,360],{"class":264},[70,6443,6444],{"class":72,"line":735},[70,6445,366],{"class":264},[70,6447,6448],{"class":72,"line":740},[70,6449,252],{"emptyLinePlaceholder":251},[70,6451,6452,6454,6456,6458],{"class":72,"line":761},[70,6453,383],{"class":76},[70,6455,386],{"class":264},[70,6457,389],{"class":76},[70,6459,392],{"class":264},[70,6461,6462],{"class":72,"line":766},[70,6463,252],{"emptyLinePlaceholder":251},[70,6465,6466,6468,6470,6472,6474,6476],{"class":72,"line":772},[70,6467,383],{"class":76},[70,6469,386],{"class":264},[70,6471,389],{"class":76},[70,6473,410],{"class":264},[70,6475,413],{"class":76},[70,6477,416],{"class":264},[70,6479,6480],{"class":72,"line":816},[70,6481,252],{"emptyLinePlaceholder":251},[70,6483,6484,6486,6488,6490],{"class":72,"line":823},[70,6485,383],{"class":76},[70,6487,386],{"class":264},[70,6489,426],{"class":76},[70,6491,429],{"class":264},[70,6493,6494],{"class":72,"line":828},[70,6495,252],{"emptyLinePlaceholder":251},[70,6497,6498,6500,6502,6504,6506,6508],{"class":72,"line":848},[70,6499,302],{"class":76},[70,6501,386],{"class":264},[70,6503,444],{"class":76},[70,6505,265],{"class":264},[70,6507,449],{"class":80},[70,6509,452],{"class":264},[70,6511,6512],{"class":72,"line":857},[70,6513,252],{"emptyLinePlaceholder":251},[70,6515,6516,6518,6520],{"class":72,"line":862},[70,6517,463],{"class":264},[70,6519,466],{"class":76},[70,6521,469],{"class":264},[70,6523,6524],{"class":72,"line":867},[70,6525,252],{"emptyLinePlaceholder":251},[70,6527,6528,6530],{"class":72,"line":884},[70,6529,325],{"class":219},[70,6531,477],{"class":264},[70,6533,6534],{"class":72,"line":901},[70,6535,343],{"class":264},[70,6537,6538,6540,6542,6544,6546,6548,6550,6552],{"class":72,"line":906},[70,6539,488],{"class":76},[70,6541,386],{"class":264},[70,6543,444],{"class":76},[70,6545,265],{"class":264},[70,6547,497],{"class":80},[70,6549,500],{"class":264},[70,6551,503],{"class":76},[70,6553,506],{"class":264},[70,6555,6556,6558,6560],{"class":72,"line":917},[70,6557,512],{"class":219},[70,6559,515],{"class":124},[70,6561,314],{"class":264},[70,6563,6564],{"class":72,"line":1618},[70,6565,366],{"class":264},[70,6567,6568],{"class":72,"line":1640},[70,6569,252],{"emptyLinePlaceholder":251},[70,6571,6572,6574,6576],{"class":72,"line":1645},[70,6573,463],{"class":264},[70,6575,535],{"class":76},[70,6577,620],{"class":264},[70,6579,6580,6582,6584,6586,6588,6590,6592,6594,6596,6598],{"class":72,"line":1661},[70,6581,626],{"class":76},[70,6583,386],{"class":264},[70,6585,389],{"class":76},[70,6587,386],{"class":264},[70,6589,549],{"class":76},[70,6591,386],{"class":264},[70,6593,554],{"class":76},[70,6595,265],{"class":264},[70,6597,559],{"class":124},[70,6599,562],{"class":264},[70,6601,6602],{"class":72,"line":1666},[70,6603,252],{"emptyLinePlaceholder":251},[70,6605,6606,6608,6610],{"class":72,"line":1672},[70,6607,463],{"class":264},[70,6609,535],{"class":76},[70,6611,620],{"class":264},[70,6613,6614,6616,6618,6620,6622,6624,6626,6628,6630,6632],{"class":72,"line":1678},[70,6615,626],{"class":76},[70,6617,386],{"class":264},[70,6619,389],{"class":76},[70,6621,386],{"class":264},[70,6623,549],{"class":76},[70,6625,386],{"class":264},[70,6627,586],{"class":76},[70,6629,265],{"class":264},[70,6631,591],{"class":124},[70,6633,562],{"class":264},[70,6635,6636],{"class":72,"line":1692},[70,6637,252],{"emptyLinePlaceholder":251},[70,6639,6640,6642,6644],{"class":72,"line":1708},[70,6641,463],{"class":264},[70,6643,535],{"class":76},[70,6645,620],{"class":264},[70,6647,6648,6650,6652,6654,6656,6658,6660,6662],{"class":72,"line":1714},[70,6649,626],{"class":76},[70,6651,386],{"class":264},[70,6653,389],{"class":76},[70,6655,386],{"class":264},[70,6657,549],{"class":76},[70,6659,386],{"class":264},[70,6661,617],{"class":76},[70,6663,620],{"class":264},[70,6665,6666,6668,6670,6672,6674,6676,6678,6680],{"class":72,"line":1730},[70,6667,1496],{"class":76},[70,6669,386],{"class":264},[70,6671,389],{"class":76},[70,6673,386],{"class":264},[70,6675,549],{"class":76},[70,6677,386],{"class":264},[70,6679,617],{"class":76},[70,6681,641],{"class":264},[70,6683,6684],{"class":72,"line":1736},[70,6685,252],{"emptyLinePlaceholder":251},[70,6687,6688,6690,6692],{"class":72,"line":1741},[70,6689,463],{"class":264},[70,6691,535],{"class":76},[70,6693,620],{"class":264},[70,6695,6696,6698,6700,6702,6704,6706,6708,6710],{"class":72,"line":1748},[70,6697,626],{"class":76},[70,6699,386],{"class":264},[70,6701,389],{"class":76},[70,6703,386],{"class":264},[70,6705,549],{"class":76},[70,6707,386],{"class":264},[70,6709,665],{"class":76},[70,6711,620],{"class":264},[70,6713,6714,6716,6718,6720,6722,6724,6726,6728],{"class":72,"line":1753},[70,6715,1496],{"class":76},[70,6717,386],{"class":264},[70,6719,389],{"class":76},[70,6721,386],{"class":264},[70,6723,549],{"class":76},[70,6725,386],{"class":264},[70,6727,665],{"class":76},[70,6729,687],{"class":264},[70,6731,6732],{"class":72,"line":1773},[70,6733,252],{"emptyLinePlaceholder":251},[70,6735,6736,6738,6740],{"class":72,"line":1782},[70,6737,463],{"class":264},[70,6739,535],{"class":76},[70,6741,620],{"class":264},[70,6743,6744,6746,6748,6750,6752,6754,6756,6758],{"class":72,"line":1787},[70,6745,626],{"class":76},[70,6747,386],{"class":264},[70,6749,389],{"class":76},[70,6751,386],{"class":264},[70,6753,549],{"class":76},[70,6755,386],{"class":264},[70,6757,711],{"class":76},[70,6759,620],{"class":264},[70,6761,6762,6764,6766,6768,6770,6772,6774,6776],{"class":72,"line":1792},[70,6763,1496],{"class":76},[70,6765,386],{"class":264},[70,6767,389],{"class":76},[70,6769,386],{"class":264},[70,6771,549],{"class":76},[70,6773,386],{"class":264},[70,6775,711],{"class":76},[70,6777,641],{"class":264},[70,6779,6780],{"class":72,"line":1798},[70,6781,252],{"emptyLinePlaceholder":251},[70,6783,6784,6786,6788,6790,6792,6794,6796],{"class":72,"line":1818},[70,6785,302],{"class":76},[70,6787,1623],{"class":264},[70,6789,1626],{"class":219},[70,6791,274],{"class":264},[70,6793,1631],{"class":124},[70,6795,1634],{"class":219},[70,6797,1637],{"class":264},[70,6799,6800],{"class":72,"line":1823},[70,6801,252],{"emptyLinePlaceholder":251},[70,6803,6804,6806,6808,6810,6812,6815],{"class":72,"line":1839},[70,6805,302],{"class":76},[70,6807,386],{"class":264},[70,6809,444],{"class":76},[70,6811,265],{"class":264},[70,6813,6814],{"class":80},"\"main：注册 async_read，等待接收 11 个字节\"",[70,6816,898],{"class":264},[70,6818,6819],{"class":72,"line":1856},[70,6820,252],{"emptyLinePlaceholder":251},[70,6822,6823,6825,6827,6829,6831,6833],{"class":72,"line":1861},[70,6824,383],{"class":76},[70,6826,386],{"class":264},[70,6828,389],{"class":76},[70,6830,386],{"class":264},[70,6832,6084],{"class":76},[70,6834,620],{"class":264},[70,6836,6837],{"class":72,"line":1876},[70,6838,3025],{"class":264},[70,6840,6841,6843,6845,6847,6849,6851],{"class":72,"line":1881},[70,6842,626],{"class":76},[70,6844,386],{"class":264},[70,6846,389],{"class":76},[70,6848,386],{"class":264},[70,6850,810],{"class":76},[70,6852,1727],{"class":264},[70,6854,6855,6857,6859,6861],{"class":72,"line":1890},[70,6856,488],{"class":76},[70,6858,386],{"class":264},[70,6860,5144],{"class":76},[70,6862,620],{"class":264},[70,6864,6865],{"class":72,"line":5216},[70,6866,6867],{"class":264},"            on_read,\n",[70,6869,6870,6872,6874,6876],{"class":72,"line":5221},[70,6871,5156],{"class":76},[70,6873,386],{"class":264},[70,6875,5161],{"class":76},[70,6877,5164],{"class":264},[70,6879,6880,6882,6884,6886],{"class":72,"line":5231},[70,6881,5156],{"class":76},[70,6883,386],{"class":264},[70,6885,5161],{"class":76},[70,6887,6888],{"class":264},"::_2,\n",[70,6890,6891,6894],{"class":72,"line":5236},[70,6892,6893],{"class":219},"            &",[70,6895,6896],{"class":264},"buffer));\n",[70,6898,6899],{"class":72,"line":5252},[70,6900,252],{"emptyLinePlaceholder":251},[70,6902,6903,6905,6907,6909,6911,6914],{"class":72,"line":5267},[70,6904,302],{"class":76},[70,6906,386],{"class":264},[70,6908,444],{"class":76},[70,6910,265],{"class":264},[70,6912,6913],{"class":80},"\"main：async_read() 已返回\"",[70,6915,898],{"class":264},[70,6917,6918],{"class":72,"line":5272},[70,6919,252],{"emptyLinePlaceholder":251},[70,6921,6922,6924,6926,6928,6930,6932],{"class":72,"line":5281},[70,6923,302],{"class":76},[70,6925,386],{"class":264},[70,6927,444],{"class":76},[70,6929,265],{"class":264},[70,6931,5211],{"class":80},[70,6933,898],{"class":264},[70,6935,6937],{"class":72,"line":6936},91,[70,6938,252],{"emptyLinePlaceholder":251},[70,6940,6942,6944,6946],{"class":72,"line":6941},92,[70,6943,5224],{"class":264},[70,6945,2237],{"class":76},[70,6947,2240],{"class":264},[70,6949,6951],{"class":72,"line":6950},93,[70,6952,252],{"emptyLinePlaceholder":251},[70,6954,6956,6958,6960,6962,6964,6966],{"class":72,"line":6955},94,[70,6957,302],{"class":76},[70,6959,386],{"class":264},[70,6961,444],{"class":76},[70,6963,265],{"class":264},[70,6965,5247],{"class":80},[70,6967,898],{"class":264},[70,6969,6971,6973,6975,6977,6979,6981],{"class":72,"line":6970},95,[70,6972,302],{"class":76},[70,6974,386],{"class":264},[70,6976,444],{"class":76},[70,6978,265],{"class":264},[70,6980,895],{"class":80},[70,6982,898],{"class":264},[70,6984,6986],{"class":72,"line":6985},96,[70,6987,252],{"emptyLinePlaceholder":251},[70,6989,6991,6993,6995],{"class":72,"line":6990},97,[70,6992,909],{"class":219},[70,6994,912],{"class":124},[70,6996,314],{"class":264},[70,6998,7000],{"class":72,"line":6999},98,[70,7001,920],{"class":264},[55,7003,930],{"id":7004},"编译运行-3",[15,7006,933],{},[22,7008,7009],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,7010,7011,7021,7027],{"__ignoreMap":28},[70,7012,7013,7015,7017,7019],{"class":72,"line":73},[70,7014,52],{"class":76},[70,7016,125],{"class":124},[70,7018,125],{"class":124},[70,7020,130],{"class":124},[70,7022,7023,7025],{"class":72,"line":133},[70,7024,136],{"class":80},[70,7026,130],{"class":124},[70,7028,7029],{"class":72,"line":141},[70,7030,144],{"class":80},[15,7032,1938],{},[15,7034,7035],{},"程序会输出：",[22,7037,7040],{"className":7038,"code":7039,"language":27,"meta":28},[25],"main：准备打开串口 \u002Fdev\u002Fpts\u002F3\nmain：注册 async_read，等待接收 11 个字节\nmain：async_read() 已返回\nmain：开始 io.run()\n",[30,7041,7039],{"__ignoreMap":28},[15,7043,7044],{},"此时程序停留在：",[22,7046,7047],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,7048,7049],{"__ignoreMap":28},[70,7050,7051,7053,7055],{"class":72,"line":73},[70,7052,2234],{"class":264},[70,7054,2237],{"class":76},[70,7056,2240],{"class":264},[15,7058,7059],{},"等待异步操作完成。",[15,7061,7062],{},"终端 3：",[22,7064,7065],{"className":64,"code":1964,"language":66,"meta":28,"style":28},[30,7066,7067],{"__ignoreMap":28},[70,7068,7069,7071,7073,7075],{"class":72,"line":73},[70,7070,1128],{"class":124},[70,7072,1973],{"class":80},[70,7074,1976],{"class":219},[70,7076,973],{"class":80},[55,7078,982],{"id":7079},"运行输出与时间顺序-3",[15,7081,7082],{},"完整输出类似：",[22,7084,7087],{"className":7085,"code":7086,"language":27,"meta":28},[25],"main：准备打开串口 \u002Fdev\u002Fpts\u002F3\nmain：注册 async_read，等待接收 11 个字节\nmain：async_read() 已返回\nmain：开始 io.run()\n\non_read：读取成功，字节数 = 11\non_read：收到的数据 = hello asio\n\nmain：io.run() 返回\nmain：程序结束\n",[30,7088,7086],{"__ignoreMap":28},[15,7090,7091],{},"这里最重要的是：",[22,7093,7095],{"className":210,"code":7094,"language":212,"meta":28,"style":28},"boost::asio::async_read(...)\n",[30,7096,7097],{"__ignoreMap":28},[70,7098,7099,7101,7103,7105,7107,7109],{"class":72,"line":73},[70,7100,540],{"class":76},[70,7102,386],{"class":264},[70,7104,389],{"class":76},[70,7106,386],{"class":264},[70,7108,6084],{"class":76},[70,7110,3449],{"class":264},[15,7112,7113],{},"不会在这里阻塞。",[15,7115,2160],{},[22,7117,7120],{"className":7118,"code":7119,"language":27,"meta":28},[25],"async_read()\n↓\n立即返回\n↓\n继续执行 main\n↓\nio.run()\n↓\n等待读取完成\n",[30,7121,7119],{"__ignoreMap":28},[40,7123],{},[55,7125,1016],{"id":7126},"本示例需要注意的点-3",[15,7128,7129],{},"同步读取：",[22,7131,7132],{"className":210,"code":3432,"language":212,"meta":28,"style":28},[30,7133,7134],{"__ignoreMap":28},[70,7135,7136,7138,7140,7142,7144,7146],{"class":72,"line":73},[70,7137,540],{"class":76},[70,7139,386],{"class":264},[70,7141,389],{"class":76},[70,7143,386],{"class":264},[70,7145,1703],{"class":76},[70,7147,3449],{"class":264},[15,7149,7150],{},"是：",[22,7152,7155],{"className":7153,"code":7154,"language":27,"meta":28},[25],"调用 read()\n↓\n当前线程阻塞\n↓\nbuffer 被填满\n↓\nread() 返回\n",[30,7156,7154],{"__ignoreMap":28},[15,7158,7159],{},"异步读取：",[22,7161,7162],{"className":210,"code":7094,"language":212,"meta":28,"style":28},[30,7163,7164],{"__ignoreMap":28},[70,7165,7166,7168,7170,7172,7174,7176],{"class":72,"line":73},[70,7167,540],{"class":76},[70,7169,386],{"class":264},[70,7171,389],{"class":76},[70,7173,386],{"class":264},[70,7175,6084],{"class":76},[70,7177,3449],{"class":264},[15,7179,7150],{},[22,7181,7184],{"className":7182,"code":7183,"language":27,"meta":28},[25],"登记一个读取任务\n↓\n立即返回\n↓\nio.run() 驱动任务\n↓\n读取完成\n↓\n调用回调\n",[30,7185,7183],{"__ignoreMap":28},[15,7187,7188],{},"本例 buffer：",[22,7190,7191],{"className":210,"code":2051,"language":212,"meta":28,"style":28},[30,7192,7193],{"__ignoreMap":28},[70,7194,7195,7197,7199,7201,7203,7205,7207],{"class":72,"line":73},[70,7196,2058],{"class":76},[70,7198,1623],{"class":264},[70,7200,1626],{"class":219},[70,7202,274],{"class":264},[70,7204,1631],{"class":124},[70,7206,1634],{"class":219},[70,7208,1637],{"class":264},[15,7210,2160],{},[22,7212,7214],{"className":210,"code":7213,"language":212,"meta":28,"style":28},"boost::asio::async_read(\n    serial,\n    boost::asio::buffer(buffer),\n    ...);\n",[30,7215,7216,7230,7234,7248],{"__ignoreMap":28},[70,7217,7218,7220,7222,7224,7226,7228],{"class":72,"line":73},[70,7219,540],{"class":76},[70,7221,386],{"class":264},[70,7223,389],{"class":76},[70,7225,386],{"class":264},[70,7227,6084],{"class":76},[70,7229,620],{"class":264},[70,7231,7232],{"class":72,"line":133},[70,7233,2026],{"class":264},[70,7235,7236,7238,7240,7242,7244,7246],{"class":72,"line":141},[70,7237,383],{"class":76},[70,7239,386],{"class":264},[70,7241,389],{"class":76},[70,7243,386],{"class":264},[70,7245,810],{"class":76},[70,7247,1727],{"class":264},[70,7249,7250],{"class":72,"line":240},[70,7251,5769],{"class":264},[15,7253,2203],{},[12,7255,7256],{},[15,7257,7258],{},"异步等待，直到这个 11 字节 buffer 被填满或者发生错误。",[15,7260,2212],{},[22,7262,7264],{"className":7263,"code":2216,"language":27,"meta":28},[25],[30,7265,2216],{"__ignoreMap":28},[15,7267,7268],{},"异步操作不会完成。",[15,7270,7271,7274],{},[30,7272,7273],{},"io.run()"," 仍然会继续等待。",[15,7276,7277],{},"直到累计收到：",[22,7279,7282],{"className":7280,"code":7281,"language":27,"meta":28},[25],"11 字节\n",[30,7283,7281],{"__ignoreMap":28},[15,7285,7286],{},"以后：",[22,7288,7290],{"className":210,"code":7289,"language":212,"meta":28,"style":28},"on_read()\n",[30,7291,7292],{"__ignoreMap":28},[70,7293,7294,7297],{"class":72,"line":73},[70,7295,7296],{"class":76},"on_read",[70,7298,3162],{"class":264},[15,7300,7301],{},"才会被调用。",[40,7303],{},[55,7305,7307,7308,7311],{"id":7306},"为什么把-buffer-额外传给回调很重要要记得","为什么把 ",[30,7309,7310],{},"&buffer"," 额外传给回调？（很重要，要记得）",[15,7313,7314],{},"Asio 在异步读取完成时，会自动给回调传入：",[22,7316,7318],{"className":210,"code":7317,"language":212,"meta":28,"style":28},"const boost::system::error_code& ec\nstd::size_t bytes_transferred\n",[30,7319,7320,7336],{"__ignoreMap":28},[70,7321,7322,7324,7326,7328,7330,7332,7334],{"class":72,"line":73},[70,7323,5601],{"class":219},[70,7325,787],{"class":76},[70,7327,386],{"class":264},[70,7329,426],{"class":76},[70,7331,5610],{"class":264},[70,7333,4549],{"class":219},[70,7335,5615],{"class":264},[70,7337,7338,7340,7342,7344],{"class":72,"line":133},[70,7339,2058],{"class":76},[70,7341,386],{"class":264},[70,7343,779],{"class":219},[70,7345,5637],{"class":264},[15,7347,7348],{},"但是它不会自动把：",[22,7350,7351],{"className":210,"code":2898,"language":212,"meta":28,"style":28},[30,7352,7353],{"__ignoreMap":28},[70,7354,7355],{"class":72,"line":73},[70,7356,2898],{"class":264},[15,7358,7359],{},"作为回调参数传给你。",[15,7361,7362],{},"所以我们使用：",[22,7364,7366],{"className":210,"code":7365,"language":212,"meta":28,"style":28},"std::bind(\n    on_read,\n    std::placeholders::_1,\n    std::placeholders::_2,\n    &buffer)\n",[30,7367,7368,7378,7383,7393,7403],{"__ignoreMap":28},[70,7369,7370,7372,7374,7376],{"class":72,"line":73},[70,7371,2058],{"class":76},[70,7373,386],{"class":264},[70,7375,5144],{"class":76},[70,7377,620],{"class":264},[70,7379,7380],{"class":72,"line":133},[70,7381,7382],{"class":264},"    on_read,\n",[70,7384,7385,7387,7389,7391],{"class":72,"line":141},[70,7386,302],{"class":76},[70,7388,386],{"class":264},[70,7390,5161],{"class":76},[70,7392,5164],{"class":264},[70,7394,7395,7397,7399,7401],{"class":72,"line":240},[70,7396,302],{"class":76},[70,7398,386],{"class":264},[70,7400,5161],{"class":76},[70,7402,6888],{"class":264},[70,7404,7405,7408],{"class":72,"line":248},[70,7406,7407],{"class":219},"    &",[70,7409,7410],{"class":264},"buffer)\n",[15,7412,7413],{},"相当于以后调用：",[22,7415,7417],{"className":210,"code":7416,"language":212,"meta":28,"style":28},"on_read(\n    ec,\n    bytes_transferred,\n    &buffer);\n",[30,7418,7419,7425,7430,7435],{"__ignoreMap":28},[70,7420,7421,7423],{"class":72,"line":73},[70,7422,7296],{"class":76},[70,7424,620],{"class":264},[70,7426,7427],{"class":72,"line":133},[70,7428,7429],{"class":264},"    ec,\n",[70,7431,7432],{"class":72,"line":141},[70,7433,7434],{"class":264},"    bytes_transferred,\n",[70,7436,7437,7439],{"class":72,"line":240},[70,7438,7407],{"class":219},[70,7440,7441],{"class":264},"buffer);\n",[15,7443,7444],{},"因此回调就可以通过：",[22,7446,7448],{"className":210,"code":7447,"language":212,"meta":28,"style":28},"buffer->data()\n",[30,7449,7450],{"__ignoreMap":28},[70,7451,7452,7455,7457],{"class":72,"line":73},[70,7453,7454],{"class":264},"buffer->",[70,7456,1812],{"class":76},[70,7458,3162],{"class":264},[15,7460,7461],{},"访问真正收到的数据。",[40,7463],{},[55,7465,7467],{"id":7466},"buffer-生命周期","buffer 生命周期",[15,7469,5703],{},[22,7471,7472],{"className":210,"code":2051,"language":212,"meta":28,"style":28},[30,7473,7474],{"__ignoreMap":28},[70,7475,7476,7478,7480,7482,7484,7486,7488],{"class":72,"line":73},[70,7477,2058],{"class":76},[70,7479,1623],{"class":264},[70,7481,1626],{"class":219},[70,7483,274],{"class":264},[70,7485,1631],{"class":124},[70,7487,1634],{"class":219},[70,7489,1637],{"class":264},[15,7491,7492],{},"必须保证在：",[22,7494,7496],{"className":210,"code":7495,"language":212,"meta":28,"style":28},"async_read()\n",[30,7497,7498],{"__ignoreMap":28},[70,7499,7500,7502],{"class":72,"line":73},[70,7501,6084],{"class":76},[70,7503,3162],{"class":264},[15,7505,7506],{},"完成之前一直存在。",[15,7508,2137],{},[22,7510,7513],{"className":7511,"code":7512,"language":27,"meta":28},[25],"buffer 创建于 main()\n↓\n注册 async_read()\n↓\nio.run()\n↓\n读取完成\n↓\non_read()\n↓\nio.run() 返回\n↓\nmain() 最后结束\n",[30,7514,7512],{"__ignoreMap":28},[15,7516,7517],{},"所以 buffer 的生命周期足够长。",[15,7519,7520],{},"这一点和异步发送中的：",[22,7522,7523],{"className":210,"code":5811,"language":212,"meta":28,"style":28},[30,7524,7525],{"__ignoreMap":28},[70,7526,7527],{"class":72,"line":73},[70,7528,5811],{"class":264},[15,7530,7531],{},"是同一个问题：",[12,7533,7534],{},[15,7535,7536],{},"异步操作使用的底层数据，在操作完成以前不能被销毁。",[40,7538],{},[55,7540,7542,5956],{"id":7541},"boostasioasync_read-说明",[30,7543,7544],{},"boost::asio::async_read()",[22,7546,7548],{"className":210,"code":7547,"language":212,"meta":28,"style":28},"boost::asio::async_read(\n    serial,\n    boost::asio::buffer(buffer),\n    handler);\n",[30,7549,7550,7564,7568,7582],{"__ignoreMap":28},[70,7551,7552,7554,7556,7558,7560,7562],{"class":72,"line":73},[70,7553,540],{"class":76},[70,7555,386],{"class":264},[70,7557,389],{"class":76},[70,7559,386],{"class":264},[70,7561,6084],{"class":76},[70,7563,620],{"class":264},[70,7565,7566],{"class":72,"line":133},[70,7567,2026],{"class":264},[70,7569,7570,7572,7574,7576,7578,7580],{"class":72,"line":141},[70,7571,383],{"class":76},[70,7573,386],{"class":264},[70,7575,389],{"class":76},[70,7577,386],{"class":264},[70,7579,810],{"class":76},[70,7581,1727],{"class":264},[70,7583,7584],{"class":72,"line":240},[70,7585,5998],{"class":264},[15,7587,6001],{},[12,7589,7590],{},[15,7591,7592],{},"异步读取，直到指定的整个 buffer 被填满或者发生错误。",[15,7594,7595],{},"它本身立即返回。",[15,7597,7598],{},"真正的读取工作由：",[22,7600,7601],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,7602,7603],{"__ignoreMap":28},[70,7604,7605,7607,7609],{"class":72,"line":73},[70,7606,2234],{"class":264},[70,7608,2237],{"class":76},[70,7610,2240],{"class":264},[15,7612,7613],{},"驱动。",[15,7615,7616],{},"完成以后调用：",[22,7618,7620],{"className":210,"code":7619,"language":212,"meta":28,"style":28},"handler(ec, bytes_transferred);\n",[30,7621,7622],{"__ignoreMap":28},[70,7623,7624,7627],{"class":72,"line":73},[70,7625,7626],{"class":76},"handler",[70,7628,7629],{"class":264},"(ec, bytes_transferred);\n",[15,7631,3227],{},[12,7633,7634],{},[15,7635,7636,7639],{},[30,7637,7638],{},"async_read()"," = “我要异步把整个 buffer 读满，完成以后调用回调”。",[40,7641],{},[43,7643,7645],{"id":7644},"示例-5类里封装异步串口写队列","示例 5：类里封装异步串口写队列",[55,7647,186],{"id":7648},"程序目标-4",[15,7650,7651],{},"前面的示例 3 已经可以异步发送一条数据：",[22,7653,7654],{"className":210,"code":5371,"language":212,"meta":28,"style":28},[30,7655,7656],{"__ignoreMap":28},[70,7657,7658,7660,7662,7664,7666,7668],{"class":72,"line":73},[70,7659,540],{"class":76},[70,7661,386],{"class":264},[70,7663,389],{"class":76},[70,7665,386],{"class":264},[70,7667,4446],{"class":76},[70,7669,3449],{"class":264},[15,7671,7672],{},"但是实际程序通常不会只发送一次。",[15,7674,7675],{},"例如可能连续调用：",[22,7677,7679],{"className":210,"code":7678,"language":212,"meta":28,"style":28},"async_send(\"message one\\n\");\nasync_send(\"message two\\n\");\nasync_send(\"message three\\n\");\n",[30,7680,7681,7697,7712],{"__ignoreMap":28},[70,7682,7683,7686,7688,7691,7693,7695],{"class":72,"line":73},[70,7684,7685],{"class":76},"async_send",[70,7687,265],{"class":264},[70,7689,7690],{"class":80},"\"message one",[70,7692,753],{"class":124},[70,7694,756],{"class":80},[70,7696,898],{"class":264},[70,7698,7699,7701,7703,7706,7708,7710],{"class":72,"line":133},[70,7700,7685],{"class":76},[70,7702,265],{"class":264},[70,7704,7705],{"class":80},"\"message two",[70,7707,753],{"class":124},[70,7709,756],{"class":80},[70,7711,898],{"class":264},[70,7713,7714,7716,7718,7721,7723,7725],{"class":72,"line":141},[70,7715,7685],{"class":76},[70,7717,265],{"class":264},[70,7719,7720],{"class":80},"\"message three",[70,7722,753],{"class":124},[70,7724,756],{"class":80},[70,7726,898],{"class":264},[15,7728,7729],{},"如果每次都直接启动一个新的：",[22,7731,7733],{"className":210,"code":7732,"language":212,"meta":28,"style":28},"async_write()\n",[30,7734,7735],{"__ignoreMap":28},[70,7736,7737,7739],{"class":72,"line":73},[70,7738,4446],{"class":76},[70,7740,3162],{"class":264},[15,7742,7743],{},"那么多个异步写操作可能同时操作同一个串口。",[15,7745,7746],{},"更稳妥的方式是建立：",[22,7748,7751],{"className":7749,"code":7750,"language":27,"meta":28},[25],"发送队列\n",[30,7752,7750],{"__ignoreMap":28},[15,7754,7755],{},"规则：",[22,7757,7760],{"className":7758,"code":7759,"language":27,"meta":28},[25],"新数据到来\n↓\n放进 write_queue_\n\n如果当前没有正在发送的数据\n↓\n立即开始发送队首\n\n如果当前已经有数据正在发送\n↓\n只加入队列，不再启动第二个写操作\n\n当前发送完成\n↓\n删除队首\n↓\n继续发送下一条\n",[30,7761,7759],{"__ignoreMap":28},[15,7763,7764],{},"最终保证：",[22,7766,7769],{"className":7767,"code":7768,"language":27,"meta":28},[25],"同一时刻\n只有一个 async_write()\n正在操作串口\n",[30,7770,7768],{"__ignoreMap":28},[55,7772,207],{"id":7773},"完整代码-4",[22,7775,7777],{"className":210,"code":7776,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Cdeque>\n#include \u003Cfunctional>\n#include \u003Cprint>\n#include \u003Cstring>\n\nclass SerialWriter\n{\npublic:\n    SerialWriter(\n        boost::asio::io_context& io,\n        const std::string& port_name)\n        : serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n\n        if (ec)\n        {\n            std::println(\n                \"打开串口失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        serial_.set_option(\n            boost::asio::serial_port_base::baud_rate(115200));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::character_size(8));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::parity(\n                boost::asio::serial_port_base::parity::none));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::stop_bits(\n                boost::asio::serial_port_base::stop_bits::one));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::flow_control(\n                boost::asio::serial_port_base::flow_control::none));\n\n        std::println(\"SerialWriter：串口打开成功\");\n    }\n\n    void async_send(const std::string& msg)\n    {\n        \u002F\u002F 队列原来非空，说明当前已经有写操作正在进行，\n        \u002F\u002F 或者已经有数据排队等待。\n        bool writing = !write_queue_.empty();\n\n        \u002F\u002F 先把数据保存到队列中。\n        \u002F\u002F 这样可以保证异步写期间字符串一直存在。\n        write_queue_.push_back(msg);\n\n        std::print(\n            \"加入发送队列：{}\",\n            msg);\n\n        \u002F\u002F 原来队列为空，说明当前没有正在执行的写操作。\n        \u002F\u002F 此时由这次调用启动整个发送链。\n        if (!writing)\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    void do_write()\n    {\n        \u002F\u002F 永远只发送队首数据。\n        boost::asio::async_write(\n            serial_,\n            boost::asio::buffer(\n                write_queue_.front()),\n            std::bind(\n                &SerialWriter::on_write,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_write(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"发送失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::println(\n            \"发送完成，字节数 = {}\",\n            bytes_transferred);\n\n        \u002F\u002F 当前队首已经发送完成，可以删除。\n        write_queue_.pop_front();\n\n        \u002F\u002F 如果后面还有数据，继续发送新的队首。\n        if (!write_queue_.empty())\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    boost::asio::serial_port serial_;\n\n    \u002F\u002F 保存等待发送以及当前正在发送的数据。\n    std::deque\u003Cstd::string> write_queue_;\n};\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    SerialWriter writer(io, port_name);\n\n    writer.async_send(\"message one\\n\");\n    writer.async_send(\"message two\\n\");\n    writer.async_send(\"message three\\n\");\n\n    std::println(\"main：开始 io.run()\");\n\n    io.run();\n\n    std::println(\n        \"main：发送队列处理完成，程序结束\");\n\n    return 0;\n}\n",[30,7778,7779,7785,7791,7798,7804,7810,7816,7820,7828,7832,7837,7844,7864,7883,7894,7898,7908,7912,7921,7925,7932,7937,7947,7954,7963,7967,7974,7979,7983,7991,8013,8017,8025,8047,8051,8059,8077,8096,8100,8108,8126,8144,8148,8156,8174,8192,8196,8211,8215,8219,8243,8247,8252,8257,8278,8282,8287,8292,8303,8307,8318,8325,8330,8334,8339,8344,8357,8361,8368,8372,8376,8380,8385,8394,8398,8403,8417,8422,8436,8447,8457,8468,8475,8486,8496,8500,8504,8512,8532,8544,8548,8554,8558,8568,8575,8583,8587,8593,8597,8602,8613,8621,8627,8632,8638,8648,8653,8659,8675,8680,8687,8692,8697,8702,8707,8719,8724,8730,8750,8756,8761,8782,8787,8800,8805,8818,8823,8836,8841,8846,8857,8862,8874,8879,8897,8914,8931,8936,8951,8956,8965,8970,8981,8989,8994,9003],{"__ignoreMap":28},[70,7780,7781,7783],{"class":72,"line":73},[70,7782,220],{"class":219},[70,7784,223],{"class":80},[70,7786,7787,7789],{"class":72,"line":133},[70,7788,220],{"class":219},[70,7790,230],{"class":80},[70,7792,7793,7795],{"class":72,"line":141},[70,7794,220],{"class":219},[70,7796,7797],{"class":80}," \u003Cdeque>\n",[70,7799,7800,7802],{"class":72,"line":240},[70,7801,220],{"class":219},[70,7803,4504],{"class":80},[70,7805,7806,7808],{"class":72,"line":248},[70,7807,220],{"class":219},[70,7809,237],{"class":80},[70,7811,7812,7814],{"class":72,"line":255},[70,7813,220],{"class":219},[70,7815,245],{"class":80},[70,7817,7818],{"class":72,"line":286},[70,7819,252],{"emptyLinePlaceholder":251},[70,7821,7822,7825],{"class":72,"line":292},[70,7823,7824],{"class":219},"class",[70,7826,7827],{"class":76}," SerialWriter\n",[70,7829,7830],{"class":72,"line":299},[70,7831,289],{"class":264},[70,7833,7834],{"class":72,"line":317},[70,7835,7836],{"class":219},"public:\n",[70,7838,7839,7842],{"class":72,"line":322},[70,7840,7841],{"class":76},"    SerialWriter",[70,7843,620],{"class":264},[70,7845,7846,7848,7850,7852,7854,7857,7859,7862],{"class":72,"line":340},[70,7847,626],{"class":76},[70,7849,386],{"class":264},[70,7851,389],{"class":76},[70,7853,386],{"class":264},[70,7855,7856],{"class":76},"io_context",[70,7858,4549],{"class":219},[70,7860,7861],{"class":270}," io",[70,7863,4555],{"class":264},[70,7865,7866,7869,7872,7874,7876,7878,7881],{"class":72,"line":346},[70,7867,7868],{"class":219},"        const",[70,7870,7871],{"class":76}," std",[70,7873,386],{"class":264},[70,7875,3196],{"class":76},[70,7877,4549],{"class":219},[70,7879,7880],{"class":270}," port_name",[70,7882,337],{"class":264},[70,7884,7885,7888,7891],{"class":72,"line":363},[70,7886,7887],{"class":264},"        : ",[70,7889,7890],{"class":76},"serial_",[70,7892,7893],{"class":264},"(io)\n",[70,7895,7896],{"class":72,"line":369},[70,7897,343],{"class":264},[70,7899,7900,7902,7904,7906],{"class":72,"line":374},[70,7901,626],{"class":76},[70,7903,386],{"class":264},[70,7905,426],{"class":76},[70,7907,429],{"class":264},[70,7909,7910],{"class":72,"line":380},[70,7911,252],{"emptyLinePlaceholder":251},[70,7913,7914,7917,7919],{"class":72,"line":395},[70,7915,7916],{"class":264},"        serial_.",[70,7918,466],{"class":76},[70,7920,469],{"class":264},[70,7922,7923],{"class":72,"line":401},[70,7924,252],{"emptyLinePlaceholder":251},[70,7926,7927,7930],{"class":72,"line":419},[70,7928,7929],{"class":219},"        if",[70,7931,477],{"class":264},[70,7933,7934],{"class":72,"line":432},[70,7935,7936],{"class":264},"        {\n",[70,7938,7939,7941,7943,7945],{"class":72,"line":437},[70,7940,5156],{"class":76},[70,7942,386],{"class":264},[70,7944,444],{"class":76},[70,7946,620],{"class":264},[70,7948,7949,7952],{"class":72,"line":455},[70,7950,7951],{"class":80},"                \"打开串口失败：{}\"",[70,7953,4555],{"class":264},[70,7955,7956,7959,7961],{"class":72,"line":460},[70,7957,7958],{"class":264},"                ec.",[70,7960,503],{"class":76},[70,7962,506],{"class":264},[70,7964,7965],{"class":72,"line":472},[70,7966,252],{"emptyLinePlaceholder":251},[70,7968,7969,7972],{"class":72,"line":480},[70,7970,7971],{"class":219},"            return",[70,7973,314],{"class":264},[70,7975,7976],{"class":72,"line":485},[70,7977,7978],{"class":264},"        }\n",[70,7980,7981],{"class":72,"line":509},[70,7982,252],{"emptyLinePlaceholder":251},[70,7984,7985,7987,7989],{"class":72,"line":520},[70,7986,7916],{"class":264},[70,7988,535],{"class":76},[70,7990,620],{"class":264},[70,7992,7993,7995,7997,7999,8001,8003,8005,8007,8009,8011],{"class":72,"line":525},[70,7994,1496],{"class":76},[70,7996,386],{"class":264},[70,7998,389],{"class":76},[70,8000,386],{"class":264},[70,8002,549],{"class":76},[70,8004,386],{"class":264},[70,8006,554],{"class":76},[70,8008,265],{"class":264},[70,8010,559],{"class":124},[70,8012,562],{"class":264},[70,8014,8015],{"class":72,"line":530},[70,8016,252],{"emptyLinePlaceholder":251},[70,8018,8019,8021,8023],{"class":72,"line":565},[70,8020,7916],{"class":264},[70,8022,535],{"class":76},[70,8024,620],{"class":264},[70,8026,8027,8029,8031,8033,8035,8037,8039,8041,8043,8045],{"class":72,"line":596},[70,8028,1496],{"class":76},[70,8030,386],{"class":264},[70,8032,389],{"class":76},[70,8034,386],{"class":264},[70,8036,549],{"class":76},[70,8038,386],{"class":264},[70,8040,586],{"class":76},[70,8042,265],{"class":264},[70,8044,591],{"class":124},[70,8046,562],{"class":264},[70,8048,8049],{"class":72,"line":623},[70,8050,252],{"emptyLinePlaceholder":251},[70,8052,8053,8055,8057],{"class":72,"line":644},[70,8054,7916],{"class":264},[70,8056,535],{"class":76},[70,8058,620],{"class":264},[70,8060,8061,8063,8065,8067,8069,8071,8073,8075],{"class":72,"line":670},[70,8062,1496],{"class":76},[70,8064,386],{"class":264},[70,8066,389],{"class":76},[70,8068,386],{"class":264},[70,8070,549],{"class":76},[70,8072,386],{"class":264},[70,8074,617],{"class":76},[70,8076,620],{"class":264},[70,8078,8079,8082,8084,8086,8088,8090,8092,8094],{"class":72,"line":690},[70,8080,8081],{"class":76},"                boost",[70,8083,386],{"class":264},[70,8085,389],{"class":76},[70,8087,386],{"class":264},[70,8089,549],{"class":76},[70,8091,386],{"class":264},[70,8093,617],{"class":76},[70,8095,641],{"class":264},[70,8097,8098],{"class":72,"line":716},[70,8099,252],{"emptyLinePlaceholder":251},[70,8101,8102,8104,8106],{"class":72,"line":735},[70,8103,7916],{"class":264},[70,8105,535],{"class":76},[70,8107,620],{"class":264},[70,8109,8110,8112,8114,8116,8118,8120,8122,8124],{"class":72,"line":740},[70,8111,1496],{"class":76},[70,8113,386],{"class":264},[70,8115,389],{"class":76},[70,8117,386],{"class":264},[70,8119,549],{"class":76},[70,8121,386],{"class":264},[70,8123,665],{"class":76},[70,8125,620],{"class":264},[70,8127,8128,8130,8132,8134,8136,8138,8140,8142],{"class":72,"line":761},[70,8129,8081],{"class":76},[70,8131,386],{"class":264},[70,8133,389],{"class":76},[70,8135,386],{"class":264},[70,8137,549],{"class":76},[70,8139,386],{"class":264},[70,8141,665],{"class":76},[70,8143,687],{"class":264},[70,8145,8146],{"class":72,"line":766},[70,8147,252],{"emptyLinePlaceholder":251},[70,8149,8150,8152,8154],{"class":72,"line":772},[70,8151,7916],{"class":264},[70,8153,535],{"class":76},[70,8155,620],{"class":264},[70,8157,8158,8160,8162,8164,8166,8168,8170,8172],{"class":72,"line":816},[70,8159,1496],{"class":76},[70,8161,386],{"class":264},[70,8163,389],{"class":76},[70,8165,386],{"class":264},[70,8167,549],{"class":76},[70,8169,386],{"class":264},[70,8171,711],{"class":76},[70,8173,620],{"class":264},[70,8175,8176,8178,8180,8182,8184,8186,8188,8190],{"class":72,"line":823},[70,8177,8081],{"class":76},[70,8179,386],{"class":264},[70,8181,389],{"class":76},[70,8183,386],{"class":264},[70,8185,549],{"class":76},[70,8187,386],{"class":264},[70,8189,711],{"class":76},[70,8191,641],{"class":264},[70,8193,8194],{"class":72,"line":828},[70,8195,252],{"emptyLinePlaceholder":251},[70,8197,8198,8200,8202,8204,8206,8209],{"class":72,"line":848},[70,8199,488],{"class":76},[70,8201,386],{"class":264},[70,8203,444],{"class":76},[70,8205,265],{"class":264},[70,8207,8208],{"class":80},"\"SerialWriter：串口打开成功\"",[70,8210,898],{"class":264},[70,8212,8213],{"class":72,"line":857},[70,8214,366],{"class":264},[70,8216,8217],{"class":72,"line":862},[70,8218,252],{"emptyLinePlaceholder":251},[70,8220,8221,8224,8227,8229,8231,8233,8235,8237,8239,8241],{"class":72,"line":867},[70,8222,8223],{"class":219},"    void",[70,8225,8226],{"class":76}," async_send",[70,8228,265],{"class":264},[70,8230,5601],{"class":219},[70,8232,7871],{"class":76},[70,8234,386],{"class":264},[70,8236,3196],{"class":76},[70,8238,4549],{"class":219},[70,8240,3199],{"class":270},[70,8242,337],{"class":264},[70,8244,8245],{"class":72,"line":884},[70,8246,343],{"class":264},[70,8248,8249],{"class":72,"line":901},[70,8250,8251],{"class":295},"        \u002F\u002F 队列原来非空，说明当前已经有写操作正在进行，\n",[70,8253,8254],{"class":72,"line":906},[70,8255,8256],{"class":295},"        \u002F\u002F 或者已经有数据排队等待。\n",[70,8258,8259,8262,8265,8267,8270,8273,8276],{"class":72,"line":917},[70,8260,8261],{"class":219},"        bool",[70,8263,8264],{"class":264}," writing ",[70,8266,308],{"class":219},[70,8268,8269],{"class":219}," !",[70,8271,8272],{"class":264},"write_queue_.",[70,8274,8275],{"class":76},"empty",[70,8277,2240],{"class":264},[70,8279,8280],{"class":72,"line":1618},[70,8281,252],{"emptyLinePlaceholder":251},[70,8283,8284],{"class":72,"line":1640},[70,8285,8286],{"class":295},"        \u002F\u002F 先把数据保存到队列中。\n",[70,8288,8289],{"class":72,"line":1645},[70,8290,8291],{"class":295},"        \u002F\u002F 这样可以保证异步写期间字符串一直存在。\n",[70,8293,8294,8297,8300],{"class":72,"line":1661},[70,8295,8296],{"class":264},"        write_queue_.",[70,8298,8299],{"class":76},"push_back",[70,8301,8302],{"class":264},"(msg);\n",[70,8304,8305],{"class":72,"line":1666},[70,8306,252],{"emptyLinePlaceholder":251},[70,8308,8309,8311,8313,8316],{"class":72,"line":1672},[70,8310,488],{"class":76},[70,8312,386],{"class":264},[70,8314,8315],{"class":76},"print",[70,8317,620],{"class":264},[70,8319,8320,8323],{"class":72,"line":1678},[70,8321,8322],{"class":80},"            \"加入发送队列：{}\"",[70,8324,4555],{"class":264},[70,8326,8327],{"class":72,"line":1692},[70,8328,8329],{"class":264},"            msg);\n",[70,8331,8332],{"class":72,"line":1708},[70,8333,252],{"emptyLinePlaceholder":251},[70,8335,8336],{"class":72,"line":1714},[70,8337,8338],{"class":295},"        \u002F\u002F 原来队列为空，说明当前没有正在执行的写操作。\n",[70,8340,8341],{"class":72,"line":1730},[70,8342,8343],{"class":295},"        \u002F\u002F 此时由这次调用启动整个发送链。\n",[70,8345,8346,8348,8351,8354],{"class":72,"line":1736},[70,8347,7929],{"class":219},[70,8349,8350],{"class":264}," (",[70,8352,8353],{"class":219},"!",[70,8355,8356],{"class":264},"writing)\n",[70,8358,8359],{"class":72,"line":1741},[70,8360,7936],{"class":264},[70,8362,8363,8366],{"class":72,"line":1748},[70,8364,8365],{"class":76},"            do_write",[70,8367,2240],{"class":264},[70,8369,8370],{"class":72,"line":1753},[70,8371,7978],{"class":264},[70,8373,8374],{"class":72,"line":1773},[70,8375,366],{"class":264},[70,8377,8378],{"class":72,"line":1782},[70,8379,252],{"emptyLinePlaceholder":251},[70,8381,8382],{"class":72,"line":1787},[70,8383,8384],{"class":219},"private:\n",[70,8386,8387,8389,8392],{"class":72,"line":1792},[70,8388,8223],{"class":219},[70,8390,8391],{"class":76}," do_write",[70,8393,3162],{"class":264},[70,8395,8396],{"class":72,"line":1798},[70,8397,343],{"class":264},[70,8399,8400],{"class":72,"line":1818},[70,8401,8402],{"class":295},"        \u002F\u002F 永远只发送队首数据。\n",[70,8404,8405,8407,8409,8411,8413,8415],{"class":72,"line":1823},[70,8406,626],{"class":76},[70,8408,386],{"class":264},[70,8410,389],{"class":76},[70,8412,386],{"class":264},[70,8414,4446],{"class":76},[70,8416,620],{"class":264},[70,8418,8419],{"class":72,"line":1839},[70,8420,8421],{"class":264},"            serial_,\n",[70,8423,8424,8426,8428,8430,8432,8434],{"class":72,"line":1856},[70,8425,1496],{"class":76},[70,8427,386],{"class":264},[70,8429,389],{"class":76},[70,8431,386],{"class":264},[70,8433,810],{"class":76},[70,8435,620],{"class":264},[70,8437,8438,8441,8444],{"class":72,"line":1861},[70,8439,8440],{"class":264},"                write_queue_.",[70,8442,8443],{"class":76},"front",[70,8445,8446],{"class":264},"()),\n",[70,8448,8449,8451,8453,8455],{"class":72,"line":1876},[70,8450,5156],{"class":76},[70,8452,386],{"class":264},[70,8454,5144],{"class":76},[70,8456,620],{"class":264},[70,8458,8459,8462,8465],{"class":72,"line":1881},[70,8460,8461],{"class":219},"                &",[70,8463,8464],{"class":76},"SerialWriter",[70,8466,8467],{"class":264},"::on_write,\n",[70,8469,8470,8473],{"class":72,"line":1890},[70,8471,8472],{"class":124},"                this",[70,8474,4555],{"class":264},[70,8476,8477,8480,8482,8484],{"class":72,"line":5216},[70,8478,8479],{"class":76},"                std",[70,8481,386],{"class":264},[70,8483,5161],{"class":76},[70,8485,5164],{"class":264},[70,8487,8488,8490,8492,8494],{"class":72,"line":5221},[70,8489,8479],{"class":76},[70,8491,386],{"class":264},[70,8493,5161],{"class":76},[70,8495,5175],{"class":264},[70,8497,8498],{"class":72,"line":5231},[70,8499,366],{"class":264},[70,8501,8502],{"class":72,"line":5236},[70,8503,252],{"emptyLinePlaceholder":251},[70,8505,8506,8508,8510],{"class":72,"line":5252},[70,8507,8223],{"class":219},[70,8509,4528],{"class":76},[70,8511,620],{"class":264},[70,8513,8514,8516,8518,8520,8522,8524,8526,8528,8530],{"class":72,"line":5267},[70,8515,7868],{"class":219},[70,8517,787],{"class":76},[70,8519,386],{"class":264},[70,8521,426],{"class":76},[70,8523,386],{"class":264},[70,8525,4546],{"class":76},[70,8527,4549],{"class":219},[70,8529,4552],{"class":270},[70,8531,4555],{"class":264},[70,8533,8534,8536,8538,8540,8542],{"class":72,"line":5272},[70,8535,488],{"class":76},[70,8537,386],{"class":264},[70,8539,779],{"class":219},[70,8541,4566],{"class":270},[70,8543,337],{"class":264},[70,8545,8546],{"class":72,"line":5281},[70,8547,343],{"class":264},[70,8549,8550,8552],{"class":72,"line":6936},[70,8551,7929],{"class":219},[70,8553,477],{"class":264},[70,8555,8556],{"class":72,"line":6941},[70,8557,7936],{"class":264},[70,8559,8560,8562,8564,8566],{"class":72,"line":6950},[70,8561,5156],{"class":76},[70,8563,386],{"class":264},[70,8565,444],{"class":76},[70,8567,620],{"class":264},[70,8569,8570,8573],{"class":72,"line":6955},[70,8571,8572],{"class":80},"                \"发送失败：{}\"",[70,8574,4555],{"class":264},[70,8576,8577,8579,8581],{"class":72,"line":6970},[70,8578,7958],{"class":264},[70,8580,503],{"class":76},[70,8582,506],{"class":264},[70,8584,8585],{"class":72,"line":6985},[70,8586,252],{"emptyLinePlaceholder":251},[70,8588,8589,8591],{"class":72,"line":6990},[70,8590,7971],{"class":219},[70,8592,314],{"class":264},[70,8594,8595],{"class":72,"line":6999},[70,8596,7978],{"class":264},[70,8598,8600],{"class":72,"line":8599},99,[70,8601,252],{"emptyLinePlaceholder":251},[70,8603,8605,8607,8609,8611],{"class":72,"line":8604},100,[70,8606,488],{"class":76},[70,8608,386],{"class":264},[70,8610,444],{"class":76},[70,8612,620],{"class":264},[70,8614,8616,8619],{"class":72,"line":8615},101,[70,8617,8618],{"class":80},"            \"发送完成，字节数 = {}\"",[70,8620,4555],{"class":264},[70,8622,8624],{"class":72,"line":8623},102,[70,8625,8626],{"class":264},"            bytes_transferred);\n",[70,8628,8630],{"class":72,"line":8629},103,[70,8631,252],{"emptyLinePlaceholder":251},[70,8633,8635],{"class":72,"line":8634},104,[70,8636,8637],{"class":295},"        \u002F\u002F 当前队首已经发送完成，可以删除。\n",[70,8639,8641,8643,8646],{"class":72,"line":8640},105,[70,8642,8296],{"class":264},[70,8644,8645],{"class":76},"pop_front",[70,8647,2240],{"class":264},[70,8649,8651],{"class":72,"line":8650},106,[70,8652,252],{"emptyLinePlaceholder":251},[70,8654,8656],{"class":72,"line":8655},107,[70,8657,8658],{"class":295},"        \u002F\u002F 如果后面还有数据，继续发送新的队首。\n",[70,8660,8662,8664,8666,8668,8670,8672],{"class":72,"line":8661},108,[70,8663,7929],{"class":219},[70,8665,8350],{"class":264},[70,8667,8353],{"class":219},[70,8669,8272],{"class":264},[70,8671,8275],{"class":76},[70,8673,8674],{"class":264},"())\n",[70,8676,8678],{"class":72,"line":8677},109,[70,8679,7936],{"class":264},[70,8681,8683,8685],{"class":72,"line":8682},110,[70,8684,8365],{"class":76},[70,8686,2240],{"class":264},[70,8688,8690],{"class":72,"line":8689},111,[70,8691,7978],{"class":264},[70,8693,8695],{"class":72,"line":8694},112,[70,8696,366],{"class":264},[70,8698,8700],{"class":72,"line":8699},113,[70,8701,252],{"emptyLinePlaceholder":251},[70,8703,8705],{"class":72,"line":8704},114,[70,8706,8384],{"class":219},[70,8708,8710,8712,8714,8716],{"class":72,"line":8709},115,[70,8711,383],{"class":76},[70,8713,386],{"class":264},[70,8715,389],{"class":76},[70,8717,8718],{"class":264},"::serial_port serial_;\n",[70,8720,8722],{"class":72,"line":8721},116,[70,8723,252],{"emptyLinePlaceholder":251},[70,8725,8727],{"class":72,"line":8726},117,[70,8728,8729],{"class":295},"    \u002F\u002F 保存等待发送以及当前正在发送的数据。\n",[70,8731,8733,8735,8738,8740,8742,8745,8747],{"class":72,"line":8732},118,[70,8734,302],{"class":76},[70,8736,8737],{"class":264},"::deque",[70,8739,6226],{"class":219},[70,8741,2058],{"class":76},[70,8743,8744],{"class":264},"::string",[70,8746,1634],{"class":219},[70,8748,8749],{"class":264}," write_queue_;\n",[70,8751,8753],{"class":72,"line":8752},119,[70,8754,8755],{"class":264},"};\n",[70,8757,8759],{"class":72,"line":8758},120,[70,8760,252],{"emptyLinePlaceholder":251},[70,8762,8764,8766,8768,8770,8772,8774,8776,8778,8780],{"class":72,"line":8763},121,[70,8765,258],{"class":219},[70,8767,261],{"class":76},[70,8769,265],{"class":264},[70,8771,258],{"class":219},[70,8773,271],{"class":270},[70,8775,274],{"class":264},[70,8777,277],{"class":219},[70,8779,280],{"class":270},[70,8781,283],{"class":264},[70,8783,8785],{"class":72,"line":8784},122,[70,8786,289],{"class":264},[70,8788,8790,8792,8794,8796,8798],{"class":72,"line":8789},123,[70,8791,302],{"class":76},[70,8793,305],{"class":264},[70,8795,308],{"class":219},[70,8797,311],{"class":80},[70,8799,314],{"class":264},[70,8801,8803],{"class":72,"line":8802},124,[70,8804,252],{"emptyLinePlaceholder":251},[70,8806,8808,8810,8812,8814,8816],{"class":72,"line":8807},125,[70,8809,325],{"class":219},[70,8811,328],{"class":264},[70,8813,331],{"class":219},[70,8815,334],{"class":124},[70,8817,337],{"class":264},[70,8819,8821],{"class":72,"line":8820},126,[70,8822,343],{"class":264},[70,8824,8826,8828,8830,8832,8834],{"class":72,"line":8825},127,[70,8827,349],{"class":264},[70,8829,308],{"class":219},[70,8831,354],{"class":264},[70,8833,357],{"class":124},[70,8835,360],{"class":264},[70,8837,8839],{"class":72,"line":8838},128,[70,8840,366],{"class":264},[70,8842,8844],{"class":72,"line":8843},129,[70,8845,252],{"emptyLinePlaceholder":251},[70,8847,8849,8851,8853,8855],{"class":72,"line":8848},130,[70,8850,383],{"class":76},[70,8852,386],{"class":264},[70,8854,389],{"class":76},[70,8856,392],{"class":264},[70,8858,8860],{"class":72,"line":8859},131,[70,8861,252],{"emptyLinePlaceholder":251},[70,8863,8865,8868,8871],{"class":72,"line":8864},132,[70,8866,8867],{"class":264},"    SerialWriter ",[70,8869,8870],{"class":76},"writer",[70,8872,8873],{"class":264},"(io, port_name);\n",[70,8875,8877],{"class":72,"line":8876},133,[70,8878,252],{"emptyLinePlaceholder":251},[70,8880,8882,8885,8887,8889,8891,8893,8895],{"class":72,"line":8881},134,[70,8883,8884],{"class":264},"    writer.",[70,8886,7685],{"class":76},[70,8888,265],{"class":264},[70,8890,7690],{"class":80},[70,8892,753],{"class":124},[70,8894,756],{"class":80},[70,8896,898],{"class":264},[70,8898,8900,8902,8904,8906,8908,8910,8912],{"class":72,"line":8899},135,[70,8901,8884],{"class":264},[70,8903,7685],{"class":76},[70,8905,265],{"class":264},[70,8907,7705],{"class":80},[70,8909,753],{"class":124},[70,8911,756],{"class":80},[70,8913,898],{"class":264},[70,8915,8917,8919,8921,8923,8925,8927,8929],{"class":72,"line":8916},136,[70,8918,8884],{"class":264},[70,8920,7685],{"class":76},[70,8922,265],{"class":264},[70,8924,7720],{"class":80},[70,8926,753],{"class":124},[70,8928,756],{"class":80},[70,8930,898],{"class":264},[70,8932,8934],{"class":72,"line":8933},137,[70,8935,252],{"emptyLinePlaceholder":251},[70,8937,8939,8941,8943,8945,8947,8949],{"class":72,"line":8938},138,[70,8940,302],{"class":76},[70,8942,386],{"class":264},[70,8944,444],{"class":76},[70,8946,265],{"class":264},[70,8948,5211],{"class":80},[70,8950,898],{"class":264},[70,8952,8954],{"class":72,"line":8953},139,[70,8955,252],{"emptyLinePlaceholder":251},[70,8957,8959,8961,8963],{"class":72,"line":8958},140,[70,8960,5224],{"class":264},[70,8962,2237],{"class":76},[70,8964,2240],{"class":264},[70,8966,8968],{"class":72,"line":8967},141,[70,8969,252],{"emptyLinePlaceholder":251},[70,8971,8973,8975,8977,8979],{"class":72,"line":8972},142,[70,8974,302],{"class":76},[70,8976,386],{"class":264},[70,8978,444],{"class":76},[70,8980,620],{"class":264},[70,8982,8984,8987],{"class":72,"line":8983},143,[70,8985,8986],{"class":80},"        \"main：发送队列处理完成，程序结束\"",[70,8988,898],{"class":264},[70,8990,8992],{"class":72,"line":8991},144,[70,8993,252],{"emptyLinePlaceholder":251},[70,8995,8997,8999,9001],{"class":72,"line":8996},145,[70,8998,909],{"class":219},[70,9000,912],{"class":124},[70,9002,314],{"class":264},[70,9004,9006],{"class":72,"line":9005},146,[70,9007,920],{"class":264},[55,9009,930],{"id":9010},"编译运行-4",[15,9012,9013],{},"终端 1：",[22,9015,9016],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,9017,9018,9028,9034],{"__ignoreMap":28},[70,9019,9020,9022,9024,9026],{"class":72,"line":73},[70,9021,52],{"class":76},[70,9023,125],{"class":124},[70,9025,125],{"class":124},[70,9027,130],{"class":124},[70,9029,9030,9032],{"class":72,"line":133},[70,9031,136],{"class":80},[70,9033,130],{"class":124},[70,9035,9036],{"class":72,"line":141},[70,9037,144],{"class":80},[15,9039,5322],{},[22,9041,9042],{"className":64,"code":963,"language":66,"meta":28,"style":28},[30,9043,9044],{"__ignoreMap":28},[70,9045,9046,9048],{"class":72,"line":73},[70,9047,970],{"class":76},[70,9049,973],{"class":80},[15,9051,9052],{},"再编译执行程序",[55,9054,982],{"id":9055},"运行输出与时间顺序-4",[15,9057,5340],{},[22,9059,9062],{"className":9060,"code":9061,"language":27,"meta":28},[25],"SerialWriter：串口打开成功\n加入发送队列：message one\n加入发送队列：message two\n加入发送队列：message three\nmain：开始 io.run()\n\n发送完成，字节数 = 12\n发送完成，字节数 = 12\n发送完成，字节数 = 14\n\nmain：发送队列处理完成，程序结束\n",[30,9063,9061],{"__ignoreMap":28},[15,9065,9066],{},[995,9067],{"alt":28,"src":9068},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789473007343-bf4595fd.webp",[15,9070,9071],{},"监听终端：",[22,9073,9076],{"className":9074,"code":9075,"language":27,"meta":28},[25],"message one\nmessage two\nmessage three\n",[30,9077,9075],{"__ignoreMap":28},[15,9079,9080],{},[995,9081],{"alt":28,"src":9082},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789472977575-3f093715.webp",[55,9084,9086,9087,9090],{"id":9085},"第一次调用-async_send-时发生了什么","第一次调用 ",[30,9088,9089],{},"async_send()"," 时发生了什么？",[15,9092,9093],{},"第一次：",[22,9095,9097],{"className":210,"code":9096,"language":212,"meta":28,"style":28},"writer.async_send(\"message one\\n\");\n",[30,9098,9099],{"__ignoreMap":28},[70,9100,9101,9104,9106,9108,9110,9112,9114],{"class":72,"line":73},[70,9102,9103],{"class":264},"writer.",[70,9105,7685],{"class":76},[70,9107,265],{"class":264},[70,9109,7690],{"class":80},[70,9111,753],{"class":124},[70,9113,756],{"class":80},[70,9115,898],{"class":264},[15,9117,9118],{},"此时：",[22,9120,9122],{"className":210,"code":9121,"language":212,"meta":28,"style":28},"write_queue_.empty()\n",[30,9123,9124],{"__ignoreMap":28},[70,9125,9126,9128,9130],{"class":72,"line":73},[70,9127,8272],{"class":264},[70,9129,8275],{"class":76},[70,9131,3162],{"class":264},[15,9133,9134],{},"为：",[22,9136,9139],{"className":9137,"code":9138,"language":27,"meta":28},[25],"true\n",[30,9140,9138],{"__ignoreMap":28},[15,9142,2160],{},[22,9144,9146],{"className":210,"code":9145,"language":212,"meta":28,"style":28},"bool writing = !write_queue_.empty();\n",[30,9147,9148],{"__ignoreMap":28},[70,9149,9150,9153,9155,9157,9159,9161,9163],{"class":72,"line":73},[70,9151,9152],{"class":219},"bool",[70,9154,8264],{"class":264},[70,9156,308],{"class":219},[70,9158,8269],{"class":219},[70,9160,8272],{"class":264},[70,9162,8275],{"class":76},[70,9164,2240],{"class":264},[15,9166,9167],{},"得到：",[22,9169,9172],{"className":9170,"code":9171,"language":27,"meta":28},[25],"writing = false\n",[30,9173,9171],{"__ignoreMap":28},[15,9175,5727],{},[22,9177,9179],{"className":210,"code":9178,"language":212,"meta":28,"style":28},"write_queue_.push_back(msg);\n",[30,9180,9181],{"__ignoreMap":28},[70,9182,9183,9185,9187],{"class":72,"line":73},[70,9184,8272],{"class":264},[70,9186,8299],{"class":76},[70,9188,8302],{"class":264},[15,9190,9191],{},"队列变成：",[22,9193,9196],{"className":9194,"code":9195,"language":27,"meta":28},[25],"[ message one ]\n",[30,9197,9195],{"__ignoreMap":28},[15,9199,2048],{},[22,9201,9203],{"className":9202,"code":9171,"language":27,"meta":28},[25],[30,9204,9171],{"__ignoreMap":28},[15,9206,9207],{},"说明原来没有正在执行的发送任务。",[15,9209,2160],{},[22,9211,9213],{"className":210,"code":9212,"language":212,"meta":28,"style":28},"do_write();\n",[30,9214,9215],{"__ignoreMap":28},[70,9216,9217,9220],{"class":72,"line":73},[70,9218,9219],{"class":76},"do_write",[70,9221,2240],{"class":264},[15,9223,9224],{},"开始异步发送：",[22,9226,9229],{"className":9227,"code":9228,"language":27,"meta":28},[25],"message one\n",[30,9230,9228],{"__ignoreMap":28},[40,9232],{},[55,9234,9236],{"id":9235},"第二次和第三次调用时发生什么","第二次和第三次调用时发生什么？",[15,9238,9239],{},"第二次：",[22,9241,9243],{"className":210,"code":9242,"language":212,"meta":28,"style":28},"writer.async_send(\"message two\\n\");\n",[30,9244,9245],{"__ignoreMap":28},[70,9246,9247,9249,9251,9253,9255,9257,9259],{"class":72,"line":73},[70,9248,9103],{"class":264},[70,9250,7685],{"class":76},[70,9252,265],{"class":264},[70,9254,7705],{"class":80},[70,9256,753],{"class":124},[70,9258,756],{"class":80},[70,9260,898],{"class":264},[15,9262,9263],{},"此时队列已经是：",[22,9265,9267],{"className":9266,"code":9195,"language":27,"meta":28},[25],[30,9268,9195],{"__ignoreMap":28},[15,9270,3182],{},[22,9272,9275],{"className":9273,"code":9274,"language":27,"meta":28},[25],"writing = true\n",[30,9276,9274],{"__ignoreMap":28},[15,9278,9279],{},"然后追加：",[22,9281,9284],{"className":9282,"code":9283,"language":27,"meta":28},[25],"[ message one ]\n[ message two ]\n",[30,9285,9283],{"__ignoreMap":28},[15,9287,9288],{},"但不会再次调用：",[22,9290,9291],{"className":210,"code":9212,"language":212,"meta":28,"style":28},[30,9292,9293],{"__ignoreMap":28},[70,9294,9295,9297],{"class":72,"line":73},[70,9296,9219],{"class":76},[70,9298,2240],{"class":264},[15,9300,2048],{},[22,9302,9304],{"className":9303,"code":9228,"language":27,"meta":28},[25],[30,9305,9228],{"__ignoreMap":28},[15,9307,9308],{},"已经在异步发送。",[15,9310,9311],{},"第三次也是一样：",[22,9313,9316],{"className":9314,"code":9315,"language":27,"meta":28},[25],"[ message one   ] ← 正在发送\n[ message two   ] ← 等待\n[ message three ] ← 等待\n",[30,9317,9315],{"__ignoreMap":28},[40,9319],{},[55,9321,9323],{"id":9322},"第一条发送完成后发生什么","第一条发送完成后发生什么？",[15,9325,9326],{},"第一条：",[22,9328,9330],{"className":9329,"code":9228,"language":27,"meta":28},[25],[30,9331,9228],{"__ignoreMap":28},[15,9333,9334],{},"发送完成以后：",[22,9336,9338],{"className":210,"code":9337,"language":212,"meta":28,"style":28},"on_write(...)\n",[30,9339,9340],{"__ignoreMap":28},[70,9341,9342,9345],{"class":72,"line":73},[70,9343,9344],{"class":76},"on_write",[70,9346,3449],{"class":264},[15,9348,9349],{},"被调用。",[15,9351,9352],{},"首先：",[22,9354,9356],{"className":210,"code":9355,"language":212,"meta":28,"style":28},"write_queue_.pop_front();\n",[30,9357,9358],{"__ignoreMap":28},[70,9359,9360,9362,9364],{"class":72,"line":73},[70,9361,8272],{"class":264},[70,9363,8645],{"class":76},[70,9365,2240],{"class":264},[15,9367,9368],{},"删除已经完成的：",[22,9370,9372],{"className":9371,"code":9228,"language":27,"meta":28},[25],[30,9373,9228],{"__ignoreMap":28},[15,9375,9191],{},[22,9377,9380],{"className":9378,"code":9379,"language":27,"meta":28},[25],"[ message two   ]\n[ message three ]\n",[30,9381,9379],{"__ignoreMap":28},[15,9383,5727],{},[22,9385,9387],{"className":210,"code":9386,"language":212,"meta":28,"style":28},"if (!write_queue_.empty())\n{\n    do_write();\n}\n",[30,9388,9389,9403,9407,9414],{"__ignoreMap":28},[70,9390,9391,9393,9395,9397,9399,9401],{"class":72,"line":73},[70,9392,2776],{"class":219},[70,9394,8350],{"class":264},[70,9396,8353],{"class":219},[70,9398,8272],{"class":264},[70,9400,8275],{"class":76},[70,9402,8674],{"class":264},[70,9404,9405],{"class":72,"line":133},[70,9406,289],{"class":264},[70,9408,9409,9412],{"class":72,"line":141},[70,9410,9411],{"class":76},"    do_write",[70,9413,2240],{"class":264},[70,9415,9416],{"class":72,"line":240},[70,9417,920],{"class":264},[15,9419,9420],{},"开始发送：",[22,9422,9425],{"className":9423,"code":9424,"language":27,"meta":28},[25],"message two\n",[30,9426,9424],{"__ignoreMap":28},[15,9428,9429],{},"所以整个过程就是：",[22,9431,9434],{"className":9432,"code":9433,"language":27,"meta":28},[25],"message one\n↓\n发送完成\n↓\npop_front()\n\nmessage two\n↓\n发送完成\n↓\npop_front()\n\nmessage three\n↓\n发送完成\n↓\npop_front()\n\n队列为空\n↓\n不再 do_write()\n↓\n没有其他异步任务\n↓\nio.run() 返回\n",[30,9435,9433],{"__ignoreMap":28},[40,9437],{},[55,9439,9441],{"id":9440},"为什么必须保存发送数据","为什么必须保存发送数据？",[15,9443,9444],{},"这里不能写成：",[22,9446,9448],{"className":210,"code":9447,"language":212,"meta":28,"style":28},"void async_send()\n{\n    std::string msg = \"hello\\n\";\n\n    boost::asio::async_write(\n        serial_,\n        boost::asio::buffer(msg),\n        ...);\n}\n",[30,9449,9450,9458,9462,9478,9482,9496,9501,9515,9520],{"__ignoreMap":28},[70,9451,9452,9454,9456],{"class":72,"line":73},[70,9453,4525],{"class":219},[70,9455,8226],{"class":76},[70,9457,3162],{"class":264},[70,9459,9460],{"class":72,"line":133},[70,9461,289],{"class":264},[70,9463,9464,9466,9468,9470,9472,9474,9476],{"class":72,"line":141},[70,9465,302],{"class":76},[70,9467,745],{"class":264},[70,9469,308],{"class":219},[70,9471,5870],{"class":80},[70,9473,753],{"class":124},[70,9475,756],{"class":80},[70,9477,314],{"class":264},[70,9479,9480],{"class":72,"line":240},[70,9481,252],{"emptyLinePlaceholder":251},[70,9483,9484,9486,9488,9490,9492,9494],{"class":72,"line":248},[70,9485,383],{"class":76},[70,9487,386],{"class":264},[70,9489,389],{"class":76},[70,9491,386],{"class":264},[70,9493,4446],{"class":76},[70,9495,620],{"class":264},[70,9497,9498],{"class":72,"line":255},[70,9499,9500],{"class":264},"        serial_,\n",[70,9502,9503,9505,9507,9509,9511,9513],{"class":72,"line":286},[70,9504,626],{"class":76},[70,9506,386],{"class":264},[70,9508,389],{"class":76},[70,9510,386],{"class":264},[70,9512,810],{"class":76},[70,9514,3662],{"class":264},[70,9516,9517],{"class":72,"line":292},[70,9518,9519],{"class":264},"        ...);\n",[70,9521,9522],{"class":72,"line":299},[70,9523,920],{"class":264},[15,9525,2048],{},[22,9527,9530],{"className":9528,"code":9529,"language":27,"meta":28},[25],"async_send() 返回\n↓\nmsg 被销毁\n↓\nasync_write 可能还没有完成\n↓\nbuffer 指向失效内存\n",[30,9531,9529],{"__ignoreMap":28},[15,9533,9534],{},"本例使用：",[22,9536,9538],{"className":210,"code":9537,"language":212,"meta":28,"style":28},"std::deque\u003Cstd::string> write_queue_;\n",[30,9539,9540],{"__ignoreMap":28},[70,9541,9542,9544,9546,9548,9550,9552,9554],{"class":72,"line":73},[70,9543,2058],{"class":76},[70,9545,8737],{"class":264},[70,9547,6226],{"class":219},[70,9549,2058],{"class":76},[70,9551,8744],{"class":264},[70,9553,1634],{"class":219},[70,9555,8749],{"class":264},[15,9557,9558],{},"把数据保存起来。",[15,9560,9561],{},"只要当前数据还没有发送完成：",[22,9563,9566],{"className":9564,"code":9565,"language":27,"meta":28},[25],"它就在 deque 中\n",[30,9567,9565],{"__ignoreMap":28},[15,9569,9334],{},[22,9571,9572],{"className":210,"code":9355,"language":212,"meta":28,"style":28},[30,9573,9574],{"__ignoreMap":28},[70,9575,9576,9578,9580],{"class":72,"line":73},[70,9577,8272],{"class":264},[70,9579,8645],{"class":76},[70,9581,2240],{"class":264},[15,9583,9584],{},"才真正删除。",[15,9586,9587],{},"所以 buffer 生命周期是安全的。",[40,9589],{},[55,9591,9593],{"id":9592},"为什么异步写串口通常需要队列","为什么异步写串口通常需要队列？",[15,9595,9596],{},"如果程序连续产生很多数据：",[22,9598,9601],{"className":9599,"code":9600,"language":27,"meta":28},[25],"数据 A\n数据 B\n数据 C\n",[30,9602,9600],{"__ignoreMap":28},[15,9604,9605],{},"我们希望：",[22,9607,9610],{"className":9608,"code":9609,"language":27,"meta":28},[25],"async_write(A)\n↓\n完成\n↓\nasync_write(B)\n↓\n完成\n↓\nasync_write(C)\n",[30,9611,9609],{"__ignoreMap":28},[15,9613,9614],{},"而不是：",[22,9616,9619],{"className":9617,"code":9618,"language":27,"meta":28},[25],"async_write(A)\nasync_write(B)\nasync_write(C)\n\n三个写操作同时进行\n",[30,9620,9618],{"__ignoreMap":28},[15,9622,9623],{},"所以写队列的核心作用是：",[12,9625,9626],{},[15,9627,9628],{},"保证同一个串口上的多次异步发送按顺序一个一个执行。",[15,9630,3227],{},[12,9632,9633],{},[15,9634,9635,9637,9638,9641,9642,9645],{},[30,9636,9089],{}," 负责“入队”，",[30,9639,9640],{},"do_write()"," 负责“发送队首”，",[30,9643,9644],{},"on_write()"," 负责“发送完成后删除队首并启动下一条”。",[40,9647],{},[43,9649,9651],{"id":9650},"示例-6类里封装连续异步串口读取","示例 6：类里封装连续异步串口读取",[55,9653,186],{"id":9654},"程序目标-5",[15,9656,9657],{},"前面的示例 4：",[22,9659,9660],{"className":210,"code":7094,"language":212,"meta":28,"style":28},[30,9661,9662],{"__ignoreMap":28},[70,9663,9664,9666,9668,9670,9672,9674],{"class":72,"line":73},[70,9665,540],{"class":76},[70,9667,386],{"class":264},[70,9669,389],{"class":76},[70,9671,386],{"class":264},[70,9673,6084],{"class":76},[70,9675,3449],{"class":264},[15,9677,9678],{},"只注册了一次异步读取。",[15,9680,9681],{},"读取完成以后：",[22,9683,9686],{"className":9684,"code":9685,"language":27,"meta":28},[25],"on_read()\n↓\n没有新的异步任务\n↓\nio.run() 返回\n↓\n程序结束\n",[30,9687,9685],{"__ignoreMap":28},[15,9689,9690],{},"真实程序通常需要：",[22,9692,9695],{"className":9693,"code":9694,"language":27,"meta":28},[25],"一直读取串口\n",[30,9696,9694],{"__ignoreMap":28},[15,9698,9699],{},"因此可以把：",[22,9701,9703],{"className":210,"code":9702,"language":212,"meta":28,"style":28},"serial_port\nbuffer\nasync_read()\n回调\n",[30,9704,9705,9710,9714,9720],{"__ignoreMap":28},[70,9706,9707],{"class":72,"line":73},[70,9708,9709],{"class":264},"serial_port\n",[70,9711,9712],{"class":72,"line":133},[70,9713,2898],{"class":264},[70,9715,9716,9718],{"class":72,"line":141},[70,9717,6084],{"class":76},[70,9719,3162],{"class":264},[70,9721,9722],{"class":72,"line":240},[70,9723,9724],{"class":264},"回调\n",[15,9726,9727],{},"全部封装进一个类。",[15,9729,9730],{},"每次读取完成以后：",[22,9732,9733],{"className":210,"code":7289,"language":212,"meta":28,"style":28},[30,9734,9735],{"__ignoreMap":28},[70,9736,9737,9739],{"class":72,"line":73},[70,9738,7296],{"class":76},[70,9740,3162],{"class":264},[15,9742,9743],{},"最后再次调用：",[22,9745,9747],{"className":210,"code":9746,"language":212,"meta":28,"style":28},"start_read();\n",[30,9748,9749],{"__ignoreMap":28},[70,9750,9751,9754],{"class":72,"line":73},[70,9752,9753],{"class":76},"start_read",[70,9755,2240],{"class":264},[15,9757,9758],{},"从而形成：",[22,9760,9763],{"className":9761,"code":9762,"language":27,"meta":28},[25],"start_read()\n↓\n等待 11 字节\n↓\non_read()\n↓\n处理数据\n↓\nstart_read()\n↓\n等待下一组 11 字节\n↓\n...\n",[30,9764,9762],{"__ignoreMap":28},[55,9766,207],{"id":9767},"完整代码-5",[22,9769,9771],{"className":210,"code":9770,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Carray>\n#include \u003Cfunctional>\n#include \u003Cprint>\n#include \u003Cstring>\n\nclass SerialReader\n{\npublic:\n    SerialReader(\n        boost::asio::io_context& io,\n        const std::string& port_name)\n        : serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n\n        if (ec)\n        {\n            std::println(\n                \"打开串口失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        serial_.set_option(\n            boost::asio::serial_port_base::baud_rate(115200));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::character_size(8));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::parity(\n                boost::asio::serial_port_base::parity::none));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::stop_bits(\n                boost::asio::serial_port_base::stop_bits::one));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::flow_control(\n                boost::asio::serial_port_base::flow_control::none));\n\n        std::println(\n            \"SerialReader：串口打开成功，开始异步读取\");\n\n        start_read();\n    }\n\nprivate:\n    void start_read()\n    {\n        std::println(\n            \"SerialReader：等待下一组 11 字节\");\n\n        boost::asio::async_read(\n            serial_,\n            boost::asio::buffer(buffer_),\n            std::bind(\n                &SerialReader::on_read,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_read(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"SerialReader::on_read 错误：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::string msg(\n            buffer_.data(),\n            bytes_transferred);\n\n        std::println(\n            \"收到数据，字节数 = {}，内容 = {}\",\n            bytes_transferred,\n            msg);\n\n        \u002F\u002F 当前数据处理完成以后，\n        \u002F\u002F 再注册下一次异步读取。\n        start_read();\n    }\n\nprivate:\n    boost::asio::serial_port serial_;\n\n    \u002F\u002F 每次固定读取 11 个字节。\n    std::array\u003Cchar, 11> buffer_{};\n};\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    SerialReader reader(io, port_name);\n\n    std::println(\n        \"main：调用 io.run()，按 Ctrl+C 结束程序\");\n\n    io.run();\n\n    std::println(\"main：io.run() 返回\");\n\n    return 0;\n}\n",[30,9772,9773,9779,9785,9791,9797,9803,9809,9813,9820,9824,9828,9835,9853,9869,9877,9881,9891,9895,9903,9907,9913,9917,9927,9933,9941,9945,9951,9955,9959,9967,9989,9993,10001,10023,10027,10035,10053,10071,10075,10083,10101,10119,10123,10131,10149,10167,10171,10181,10188,10192,10199,10203,10207,10211,10220,10224,10234,10241,10245,10259,10263,10278,10288,10298,10304,10314,10324,10328,10332,10340,10360,10372,10376,10382,10386,10396,10403,10411,10415,10421,10425,10429,10439,10448,10452,10456,10466,10473,10478,10482,10486,10491,10496,10502,10506,10510,10514,10524,10528,10533,10550,10554,10558,10578,10582,10594,10598,10610,10614,10626,10630,10634,10644,10648,10658,10662,10672,10679,10683,10691,10695,10709,10713,10721],{"__ignoreMap":28},[70,9774,9775,9777],{"class":72,"line":73},[70,9776,220],{"class":219},[70,9778,223],{"class":80},[70,9780,9781,9783],{"class":72,"line":133},[70,9782,220],{"class":219},[70,9784,230],{"class":80},[70,9786,9787,9789],{"class":72,"line":141},[70,9788,220],{"class":219},[70,9790,1172],{"class":80},[70,9792,9793,9795],{"class":72,"line":240},[70,9794,220],{"class":219},[70,9796,4504],{"class":80},[70,9798,9799,9801],{"class":72,"line":248},[70,9800,220],{"class":219},[70,9802,237],{"class":80},[70,9804,9805,9807],{"class":72,"line":255},[70,9806,220],{"class":219},[70,9808,245],{"class":80},[70,9810,9811],{"class":72,"line":286},[70,9812,252],{"emptyLinePlaceholder":251},[70,9814,9815,9817],{"class":72,"line":292},[70,9816,7824],{"class":219},[70,9818,9819],{"class":76}," SerialReader\n",[70,9821,9822],{"class":72,"line":299},[70,9823,289],{"class":264},[70,9825,9826],{"class":72,"line":317},[70,9827,7836],{"class":219},[70,9829,9830,9833],{"class":72,"line":322},[70,9831,9832],{"class":76},"    SerialReader",[70,9834,620],{"class":264},[70,9836,9837,9839,9841,9843,9845,9847,9849,9851],{"class":72,"line":340},[70,9838,626],{"class":76},[70,9840,386],{"class":264},[70,9842,389],{"class":76},[70,9844,386],{"class":264},[70,9846,7856],{"class":76},[70,9848,4549],{"class":219},[70,9850,7861],{"class":270},[70,9852,4555],{"class":264},[70,9854,9855,9857,9859,9861,9863,9865,9867],{"class":72,"line":346},[70,9856,7868],{"class":219},[70,9858,7871],{"class":76},[70,9860,386],{"class":264},[70,9862,3196],{"class":76},[70,9864,4549],{"class":219},[70,9866,7880],{"class":270},[70,9868,337],{"class":264},[70,9870,9871,9873,9875],{"class":72,"line":363},[70,9872,7887],{"class":264},[70,9874,7890],{"class":76},[70,9876,7893],{"class":264},[70,9878,9879],{"class":72,"line":369},[70,9880,343],{"class":264},[70,9882,9883,9885,9887,9889],{"class":72,"line":374},[70,9884,626],{"class":76},[70,9886,386],{"class":264},[70,9888,426],{"class":76},[70,9890,429],{"class":264},[70,9892,9893],{"class":72,"line":380},[70,9894,252],{"emptyLinePlaceholder":251},[70,9896,9897,9899,9901],{"class":72,"line":395},[70,9898,7916],{"class":264},[70,9900,466],{"class":76},[70,9902,469],{"class":264},[70,9904,9905],{"class":72,"line":401},[70,9906,252],{"emptyLinePlaceholder":251},[70,9908,9909,9911],{"class":72,"line":419},[70,9910,7929],{"class":219},[70,9912,477],{"class":264},[70,9914,9915],{"class":72,"line":432},[70,9916,7936],{"class":264},[70,9918,9919,9921,9923,9925],{"class":72,"line":437},[70,9920,5156],{"class":76},[70,9922,386],{"class":264},[70,9924,444],{"class":76},[70,9926,620],{"class":264},[70,9928,9929,9931],{"class":72,"line":455},[70,9930,7951],{"class":80},[70,9932,4555],{"class":264},[70,9934,9935,9937,9939],{"class":72,"line":460},[70,9936,7958],{"class":264},[70,9938,503],{"class":76},[70,9940,506],{"class":264},[70,9942,9943],{"class":72,"line":472},[70,9944,252],{"emptyLinePlaceholder":251},[70,9946,9947,9949],{"class":72,"line":480},[70,9948,7971],{"class":219},[70,9950,314],{"class":264},[70,9952,9953],{"class":72,"line":485},[70,9954,7978],{"class":264},[70,9956,9957],{"class":72,"line":509},[70,9958,252],{"emptyLinePlaceholder":251},[70,9960,9961,9963,9965],{"class":72,"line":520},[70,9962,7916],{"class":264},[70,9964,535],{"class":76},[70,9966,620],{"class":264},[70,9968,9969,9971,9973,9975,9977,9979,9981,9983,9985,9987],{"class":72,"line":525},[70,9970,1496],{"class":76},[70,9972,386],{"class":264},[70,9974,389],{"class":76},[70,9976,386],{"class":264},[70,9978,549],{"class":76},[70,9980,386],{"class":264},[70,9982,554],{"class":76},[70,9984,265],{"class":264},[70,9986,559],{"class":124},[70,9988,562],{"class":264},[70,9990,9991],{"class":72,"line":530},[70,9992,252],{"emptyLinePlaceholder":251},[70,9994,9995,9997,9999],{"class":72,"line":565},[70,9996,7916],{"class":264},[70,9998,535],{"class":76},[70,10000,620],{"class":264},[70,10002,10003,10005,10007,10009,10011,10013,10015,10017,10019,10021],{"class":72,"line":596},[70,10004,1496],{"class":76},[70,10006,386],{"class":264},[70,10008,389],{"class":76},[70,10010,386],{"class":264},[70,10012,549],{"class":76},[70,10014,386],{"class":264},[70,10016,586],{"class":76},[70,10018,265],{"class":264},[70,10020,591],{"class":124},[70,10022,562],{"class":264},[70,10024,10025],{"class":72,"line":623},[70,10026,252],{"emptyLinePlaceholder":251},[70,10028,10029,10031,10033],{"class":72,"line":644},[70,10030,7916],{"class":264},[70,10032,535],{"class":76},[70,10034,620],{"class":264},[70,10036,10037,10039,10041,10043,10045,10047,10049,10051],{"class":72,"line":670},[70,10038,1496],{"class":76},[70,10040,386],{"class":264},[70,10042,389],{"class":76},[70,10044,386],{"class":264},[70,10046,549],{"class":76},[70,10048,386],{"class":264},[70,10050,617],{"class":76},[70,10052,620],{"class":264},[70,10054,10055,10057,10059,10061,10063,10065,10067,10069],{"class":72,"line":690},[70,10056,8081],{"class":76},[70,10058,386],{"class":264},[70,10060,389],{"class":76},[70,10062,386],{"class":264},[70,10064,549],{"class":76},[70,10066,386],{"class":264},[70,10068,617],{"class":76},[70,10070,641],{"class":264},[70,10072,10073],{"class":72,"line":716},[70,10074,252],{"emptyLinePlaceholder":251},[70,10076,10077,10079,10081],{"class":72,"line":735},[70,10078,7916],{"class":264},[70,10080,535],{"class":76},[70,10082,620],{"class":264},[70,10084,10085,10087,10089,10091,10093,10095,10097,10099],{"class":72,"line":740},[70,10086,1496],{"class":76},[70,10088,386],{"class":264},[70,10090,389],{"class":76},[70,10092,386],{"class":264},[70,10094,549],{"class":76},[70,10096,386],{"class":264},[70,10098,665],{"class":76},[70,10100,620],{"class":264},[70,10102,10103,10105,10107,10109,10111,10113,10115,10117],{"class":72,"line":761},[70,10104,8081],{"class":76},[70,10106,386],{"class":264},[70,10108,389],{"class":76},[70,10110,386],{"class":264},[70,10112,549],{"class":76},[70,10114,386],{"class":264},[70,10116,665],{"class":76},[70,10118,687],{"class":264},[70,10120,10121],{"class":72,"line":766},[70,10122,252],{"emptyLinePlaceholder":251},[70,10124,10125,10127,10129],{"class":72,"line":772},[70,10126,7916],{"class":264},[70,10128,535],{"class":76},[70,10130,620],{"class":264},[70,10132,10133,10135,10137,10139,10141,10143,10145,10147],{"class":72,"line":816},[70,10134,1496],{"class":76},[70,10136,386],{"class":264},[70,10138,389],{"class":76},[70,10140,386],{"class":264},[70,10142,549],{"class":76},[70,10144,386],{"class":264},[70,10146,711],{"class":76},[70,10148,620],{"class":264},[70,10150,10151,10153,10155,10157,10159,10161,10163,10165],{"class":72,"line":823},[70,10152,8081],{"class":76},[70,10154,386],{"class":264},[70,10156,389],{"class":76},[70,10158,386],{"class":264},[70,10160,549],{"class":76},[70,10162,386],{"class":264},[70,10164,711],{"class":76},[70,10166,641],{"class":264},[70,10168,10169],{"class":72,"line":828},[70,10170,252],{"emptyLinePlaceholder":251},[70,10172,10173,10175,10177,10179],{"class":72,"line":848},[70,10174,488],{"class":76},[70,10176,386],{"class":264},[70,10178,444],{"class":76},[70,10180,620],{"class":264},[70,10182,10183,10186],{"class":72,"line":857},[70,10184,10185],{"class":80},"            \"SerialReader：串口打开成功，开始异步读取\"",[70,10187,898],{"class":264},[70,10189,10190],{"class":72,"line":862},[70,10191,252],{"emptyLinePlaceholder":251},[70,10193,10194,10197],{"class":72,"line":867},[70,10195,10196],{"class":76},"        start_read",[70,10198,2240],{"class":264},[70,10200,10201],{"class":72,"line":884},[70,10202,366],{"class":264},[70,10204,10205],{"class":72,"line":901},[70,10206,252],{"emptyLinePlaceholder":251},[70,10208,10209],{"class":72,"line":906},[70,10210,8384],{"class":219},[70,10212,10213,10215,10218],{"class":72,"line":917},[70,10214,8223],{"class":219},[70,10216,10217],{"class":76}," start_read",[70,10219,3162],{"class":264},[70,10221,10222],{"class":72,"line":1618},[70,10223,343],{"class":264},[70,10225,10226,10228,10230,10232],{"class":72,"line":1640},[70,10227,488],{"class":76},[70,10229,386],{"class":264},[70,10231,444],{"class":76},[70,10233,620],{"class":264},[70,10235,10236,10239],{"class":72,"line":1645},[70,10237,10238],{"class":80},"            \"SerialReader：等待下一组 11 字节\"",[70,10240,898],{"class":264},[70,10242,10243],{"class":72,"line":1661},[70,10244,252],{"emptyLinePlaceholder":251},[70,10246,10247,10249,10251,10253,10255,10257],{"class":72,"line":1666},[70,10248,626],{"class":76},[70,10250,386],{"class":264},[70,10252,389],{"class":76},[70,10254,386],{"class":264},[70,10256,6084],{"class":76},[70,10258,620],{"class":264},[70,10260,10261],{"class":72,"line":1672},[70,10262,8421],{"class":264},[70,10264,10265,10267,10269,10271,10273,10275],{"class":72,"line":1678},[70,10266,1496],{"class":76},[70,10268,386],{"class":264},[70,10270,389],{"class":76},[70,10272,386],{"class":264},[70,10274,810],{"class":76},[70,10276,10277],{"class":264},"(buffer_),\n",[70,10279,10280,10282,10284,10286],{"class":72,"line":1692},[70,10281,5156],{"class":76},[70,10283,386],{"class":264},[70,10285,5144],{"class":76},[70,10287,620],{"class":264},[70,10289,10290,10292,10295],{"class":72,"line":1708},[70,10291,8461],{"class":219},[70,10293,10294],{"class":76},"SerialReader",[70,10296,10297],{"class":264},"::on_read,\n",[70,10299,10300,10302],{"class":72,"line":1714},[70,10301,8472],{"class":124},[70,10303,4555],{"class":264},[70,10305,10306,10308,10310,10312],{"class":72,"line":1730},[70,10307,8479],{"class":76},[70,10309,386],{"class":264},[70,10311,5161],{"class":76},[70,10313,5164],{"class":264},[70,10315,10316,10318,10320,10322],{"class":72,"line":1736},[70,10317,8479],{"class":76},[70,10319,386],{"class":264},[70,10321,5161],{"class":76},[70,10323,5175],{"class":264},[70,10325,10326],{"class":72,"line":1741},[70,10327,366],{"class":264},[70,10329,10330],{"class":72,"line":1748},[70,10331,252],{"emptyLinePlaceholder":251},[70,10333,10334,10336,10338],{"class":72,"line":1753},[70,10335,8223],{"class":219},[70,10337,6181],{"class":76},[70,10339,620],{"class":264},[70,10341,10342,10344,10346,10348,10350,10352,10354,10356,10358],{"class":72,"line":1773},[70,10343,7868],{"class":219},[70,10345,787],{"class":76},[70,10347,386],{"class":264},[70,10349,426],{"class":76},[70,10351,386],{"class":264},[70,10353,4546],{"class":76},[70,10355,4549],{"class":219},[70,10357,4552],{"class":270},[70,10359,4555],{"class":264},[70,10361,10362,10364,10366,10368,10370],{"class":72,"line":1782},[70,10363,488],{"class":76},[70,10365,386],{"class":264},[70,10367,779],{"class":219},[70,10369,4566],{"class":270},[70,10371,337],{"class":264},[70,10373,10374],{"class":72,"line":1787},[70,10375,343],{"class":264},[70,10377,10378,10380],{"class":72,"line":1792},[70,10379,7929],{"class":219},[70,10381,477],{"class":264},[70,10383,10384],{"class":72,"line":1798},[70,10385,7936],{"class":264},[70,10387,10388,10390,10392,10394],{"class":72,"line":1818},[70,10389,5156],{"class":76},[70,10391,386],{"class":264},[70,10393,444],{"class":76},[70,10395,620],{"class":264},[70,10397,10398,10401],{"class":72,"line":1823},[70,10399,10400],{"class":80},"                \"SerialReader::on_read 错误：{}\"",[70,10402,4555],{"class":264},[70,10404,10405,10407,10409],{"class":72,"line":1839},[70,10406,7958],{"class":264},[70,10408,503],{"class":76},[70,10410,506],{"class":264},[70,10412,10413],{"class":72,"line":1856},[70,10414,252],{"emptyLinePlaceholder":251},[70,10416,10417,10419],{"class":72,"line":1861},[70,10418,7971],{"class":219},[70,10420,314],{"class":264},[70,10422,10423],{"class":72,"line":1876},[70,10424,7978],{"class":264},[70,10426,10427],{"class":72,"line":1881},[70,10428,252],{"emptyLinePlaceholder":251},[70,10430,10431,10433,10435,10437],{"class":72,"line":1890},[70,10432,488],{"class":76},[70,10434,1803],{"class":264},[70,10436,1806],{"class":76},[70,10438,620],{"class":264},[70,10440,10441,10444,10446],{"class":72,"line":5216},[70,10442,10443],{"class":264},"            buffer_.",[70,10445,1812],{"class":76},[70,10447,6310],{"class":264},[70,10449,10450],{"class":72,"line":5221},[70,10451,8626],{"class":264},[70,10453,10454],{"class":72,"line":5231},[70,10455,252],{"emptyLinePlaceholder":251},[70,10457,10458,10460,10462,10464],{"class":72,"line":5236},[70,10459,488],{"class":76},[70,10461,386],{"class":264},[70,10463,444],{"class":76},[70,10465,620],{"class":264},[70,10467,10468,10471],{"class":72,"line":5252},[70,10469,10470],{"class":80},"            \"收到数据，字节数 = {}，内容 = {}\"",[70,10472,4555],{"class":264},[70,10474,10475],{"class":72,"line":5267},[70,10476,10477],{"class":264},"            bytes_transferred,\n",[70,10479,10480],{"class":72,"line":5272},[70,10481,8329],{"class":264},[70,10483,10484],{"class":72,"line":5281},[70,10485,252],{"emptyLinePlaceholder":251},[70,10487,10488],{"class":72,"line":6936},[70,10489,10490],{"class":295},"        \u002F\u002F 当前数据处理完成以后，\n",[70,10492,10493],{"class":72,"line":6941},[70,10494,10495],{"class":295},"        \u002F\u002F 再注册下一次异步读取。\n",[70,10497,10498,10500],{"class":72,"line":6950},[70,10499,10196],{"class":76},[70,10501,2240],{"class":264},[70,10503,10504],{"class":72,"line":6955},[70,10505,366],{"class":264},[70,10507,10508],{"class":72,"line":6970},[70,10509,252],{"emptyLinePlaceholder":251},[70,10511,10512],{"class":72,"line":6985},[70,10513,8384],{"class":219},[70,10515,10516,10518,10520,10522],{"class":72,"line":6990},[70,10517,383],{"class":76},[70,10519,386],{"class":264},[70,10521,389],{"class":76},[70,10523,8718],{"class":264},[70,10525,10526],{"class":72,"line":6999},[70,10527,252],{"emptyLinePlaceholder":251},[70,10529,10530],{"class":72,"line":8599},[70,10531,10532],{"class":295},"    \u002F\u002F 每次固定读取 11 个字节。\n",[70,10534,10535,10537,10539,10541,10543,10545,10547],{"class":72,"line":8604},[70,10536,302],{"class":76},[70,10538,1623],{"class":264},[70,10540,1626],{"class":219},[70,10542,274],{"class":264},[70,10544,1631],{"class":124},[70,10546,1634],{"class":219},[70,10548,10549],{"class":264}," buffer_{};\n",[70,10551,10552],{"class":72,"line":8615},[70,10553,8755],{"class":264},[70,10555,10556],{"class":72,"line":8623},[70,10557,252],{"emptyLinePlaceholder":251},[70,10559,10560,10562,10564,10566,10568,10570,10572,10574,10576],{"class":72,"line":8629},[70,10561,258],{"class":219},[70,10563,261],{"class":76},[70,10565,265],{"class":264},[70,10567,258],{"class":219},[70,10569,271],{"class":270},[70,10571,274],{"class":264},[70,10573,277],{"class":219},[70,10575,280],{"class":270},[70,10577,283],{"class":264},[70,10579,10580],{"class":72,"line":8634},[70,10581,289],{"class":264},[70,10583,10584,10586,10588,10590,10592],{"class":72,"line":8640},[70,10585,302],{"class":76},[70,10587,305],{"class":264},[70,10589,308],{"class":219},[70,10591,311],{"class":80},[70,10593,314],{"class":264},[70,10595,10596],{"class":72,"line":8650},[70,10597,252],{"emptyLinePlaceholder":251},[70,10599,10600,10602,10604,10606,10608],{"class":72,"line":8655},[70,10601,325],{"class":219},[70,10603,328],{"class":264},[70,10605,331],{"class":219},[70,10607,334],{"class":124},[70,10609,337],{"class":264},[70,10611,10612],{"class":72,"line":8661},[70,10613,343],{"class":264},[70,10615,10616,10618,10620,10622,10624],{"class":72,"line":8677},[70,10617,349],{"class":264},[70,10619,308],{"class":219},[70,10621,354],{"class":264},[70,10623,357],{"class":124},[70,10625,360],{"class":264},[70,10627,10628],{"class":72,"line":8682},[70,10629,366],{"class":264},[70,10631,10632],{"class":72,"line":8689},[70,10633,252],{"emptyLinePlaceholder":251},[70,10635,10636,10638,10640,10642],{"class":72,"line":8694},[70,10637,383],{"class":76},[70,10639,386],{"class":264},[70,10641,389],{"class":76},[70,10643,392],{"class":264},[70,10645,10646],{"class":72,"line":8699},[70,10647,252],{"emptyLinePlaceholder":251},[70,10649,10650,10653,10656],{"class":72,"line":8704},[70,10651,10652],{"class":264},"    SerialReader ",[70,10654,10655],{"class":76},"reader",[70,10657,8873],{"class":264},[70,10659,10660],{"class":72,"line":8709},[70,10661,252],{"emptyLinePlaceholder":251},[70,10663,10664,10666,10668,10670],{"class":72,"line":8721},[70,10665,302],{"class":76},[70,10667,386],{"class":264},[70,10669,444],{"class":76},[70,10671,620],{"class":264},[70,10673,10674,10677],{"class":72,"line":8726},[70,10675,10676],{"class":80},"        \"main：调用 io.run()，按 Ctrl+C 结束程序\"",[70,10678,898],{"class":264},[70,10680,10681],{"class":72,"line":8732},[70,10682,252],{"emptyLinePlaceholder":251},[70,10684,10685,10687,10689],{"class":72,"line":8752},[70,10686,5224],{"class":264},[70,10688,2237],{"class":76},[70,10690,2240],{"class":264},[70,10692,10693],{"class":72,"line":8758},[70,10694,252],{"emptyLinePlaceholder":251},[70,10696,10697,10699,10701,10703,10705,10707],{"class":72,"line":8763},[70,10698,302],{"class":76},[70,10700,386],{"class":264},[70,10702,444],{"class":76},[70,10704,265],{"class":264},[70,10706,5247],{"class":80},[70,10708,898],{"class":264},[70,10710,10711],{"class":72,"line":8784},[70,10712,252],{"emptyLinePlaceholder":251},[70,10714,10715,10717,10719],{"class":72,"line":8789},[70,10716,909],{"class":219},[70,10718,912],{"class":124},[70,10720,314],{"class":264},[70,10722,10723],{"class":72,"line":8802},[70,10724,920],{"class":264},[55,10726,930],{"id":10727},"编译运行-5",[15,10729,9013],{},[22,10731,10732],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,10733,10734,10744,10750],{"__ignoreMap":28},[70,10735,10736,10738,10740,10742],{"class":72,"line":73},[70,10737,52],{"class":76},[70,10739,125],{"class":124},[70,10741,125],{"class":124},[70,10743,130],{"class":124},[70,10745,10746,10748],{"class":72,"line":133},[70,10747,136],{"class":80},[70,10749,130],{"class":124},[70,10751,10752],{"class":72,"line":141},[70,10753,144],{"class":80},[15,10755,10756],{},"程序编译运行",[15,10758,10759],{},"程序输出：",[22,10761,10764],{"className":10762,"code":10763,"language":27,"meta":28},[25],"SerialReader：串口打开成功，开始异步读取\nSerialReader：等待下一组 11 字节\nmain：调用 io.run()，按 Ctrl+C 结束程序\n",[30,10765,10763],{"__ignoreMap":28},[15,10767,10768],{},"终端 2 可以连续发送：",[22,10770,10772],{"className":64,"code":10771,"language":66,"meta":28,"style":28},"printf 'hello asio\\n' > \u002Fdev\u002Fpts\u002F4\nprintf 'serial c++\\n' > \u002Fdev\u002Fpts\u002F4\nprintf 'async asio\\n' > \u002Fdev\u002Fpts\u002F4\n",[30,10773,10774,10786,10797],{"__ignoreMap":28},[70,10775,10776,10779,10782,10784],{"class":72,"line":73},[70,10777,10778],{"class":124},"printf",[70,10780,10781],{"class":80}," 'hello asio\\n'",[70,10783,1976],{"class":219},[70,10785,973],{"class":80},[70,10787,10788,10790,10793,10795],{"class":72,"line":133},[70,10789,10778],{"class":124},[70,10791,10792],{"class":80}," 'serial c++\\n'",[70,10794,1976],{"class":219},[70,10796,973],{"class":80},[70,10798,10799,10801,10804,10806],{"class":72,"line":141},[70,10800,10778],{"class":124},[70,10802,10803],{"class":80}," 'async asio\\n'",[70,10805,1976],{"class":219},[70,10807,973],{"class":80},[15,10809,10810],{},"这三组数据都是 11 字节。",[55,10812,982],{"id":10813},"运行输出与时间顺序-5",[15,10815,10816],{},"程序可能输出：",[22,10818,10821],{"className":10819,"code":10820,"language":27,"meta":28},[25],"SerialReader：串口打开成功，开始异步读取\nSerialReader：等待下一组 11 字节\nmain：调用 io.run()，按 Ctrl+C 结束程序\n\n收到数据，字节数 = 11，内容 = hello asio\nSerialReader：等待下一组 11 字节\n\n收到数据，字节数 = 11，内容 = serial c++\nSerialReader：等待下一组 11 字节\n\n收到数据，字节数 = 11，内容 = async asio\nSerialReader：等待下一组 11 字节\n",[30,10822,10820],{"__ignoreMap":28},[15,10824,10825],{},[995,10826],{"alt":28,"src":10827},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789473980474-9b421a41.webp",[15,10829,10830],{},[995,10831],{"alt":28,"src":10832},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789474015120-94faf795.webp",[15,10834,10835],{},"程序不会自动结束。",[15,10837,10838],{},"原因是每次：",[22,10840,10841],{"className":210,"code":7289,"language":212,"meta":28,"style":28},[30,10842,10843],{"__ignoreMap":28},[70,10844,10845,10847],{"class":72,"line":73},[70,10846,7296],{"class":76},[70,10848,3162],{"class":264},[15,10850,10851],{},"执行到最后都会再次：",[22,10853,10854],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,10855,10856],{"__ignoreMap":28},[70,10857,10858,10860],{"class":72,"line":73},[70,10859,9753],{"class":76},[70,10861,2240],{"class":264},[15,10863,10864],{},"注册新的异步任务。",[15,10866,2160],{},[22,10868,10869],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,10870,10871],{"__ignoreMap":28},[70,10872,10873,10875,10877],{"class":72,"line":73},[70,10874,2234],{"class":264},[70,10876,2237],{"class":76},[70,10878,2240],{"class":264},[15,10880,10881],{},"一直有尚未完成的异步读取任务需要等待。",[40,10883],{},[55,10885,10887],{"id":10886},"连续异步读取是怎么形成的","连续异步读取是怎么形成的？",[15,10889,10890],{},"程序刚创建对象：",[22,10892,10894],{"className":210,"code":10893,"language":212,"meta":28,"style":28},"SerialReader reader(io, port_name);\n",[30,10895,10896],{"__ignoreMap":28},[70,10897,10898,10900,10903,10905,10908,10910,10913],{"class":72,"line":73},[70,10899,10294],{"class":76},[70,10901,10902],{"class":76}," reader",[70,10904,265],{"class":264},[70,10906,10907],{"class":76},"io",[70,10909,274],{"class":264},[70,10911,10912],{"class":76},"port_name",[70,10914,898],{"class":264},[15,10916,10917],{},"构造函数最后：",[22,10919,10920],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,10921,10922],{"__ignoreMap":28},[70,10923,10924,10926],{"class":72,"line":73},[70,10925,9753],{"class":76},[70,10927,2240],{"class":264},[15,10929,10930],{},"第一次注册：",[22,10932,10935],{"className":10933,"code":10934,"language":27,"meta":28},[25],"async_read()\n↓\n等待 11 字节\n",[30,10936,10934],{"__ignoreMap":28},[15,10938,10939],{},"收到以后：",[22,10941,10944],{"className":10942,"code":10943,"language":27,"meta":28},[25],"on_read()\n↓\n打印数据\n↓\nstart_read()\n",[30,10945,10943],{"__ignoreMap":28},[15,10947,10948],{},"又注册一次：",[22,10950,10953],{"className":10951,"code":10952,"language":27,"meta":28},[25],"async_read()\n↓\n等待下一组 11 字节\n",[30,10954,10952],{"__ignoreMap":28},[15,10956,10957],{},"所以形成：",[22,10959,10962],{"className":10960,"code":10961,"language":27,"meta":28},[25],"start_read()\n    ↓\nasync_read()\n    ↓\n等待数据\n    ↓\non_read()\n    ↓\n处理数据\n    ↓\nstart_read()\n    ↓\nasync_read()\n    ↓\n等待下一组数据\n    ↓\n...\n",[30,10963,10961],{"__ignoreMap":28},[15,10965,10966],{},"这一句：",[22,10968,10969],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,10970,10971],{"__ignoreMap":28},[70,10972,10973,10975],{"class":72,"line":73},[70,10974,9753],{"class":76},[70,10976,2240],{"class":264},[15,10978,10979],{},"是实现连续异步读取的关键。",[15,10981,10982],{},"如果删掉它：",[22,10984,10986],{"className":210,"code":10985,"language":212,"meta":28,"style":28},"void on_read(...)\n{\n    ...\n\n    \u002F\u002F 没有 start_read();\n}\n",[30,10987,10988,10996,11000,11005,11009,11014],{"__ignoreMap":28},[70,10989,10990,10992,10994],{"class":72,"line":73},[70,10991,4525],{"class":219},[70,10993,6181],{"class":76},[70,10995,3449],{"class":264},[70,10997,10998],{"class":72,"line":133},[70,10999,289],{"class":264},[70,11001,11002],{"class":72,"line":141},[70,11003,11004],{"class":264},"    ...\n",[70,11006,11007],{"class":72,"line":240},[70,11008,252],{"emptyLinePlaceholder":251},[70,11010,11011],{"class":72,"line":248},[70,11012,11013],{"class":295},"    \u002F\u002F 没有 start_read();\n",[70,11015,11016],{"class":72,"line":255},[70,11017,920],{"class":264},[15,11019,11020],{},"那么程序只读取一次。",[15,11022,9093],{},[22,11024,11027],{"className":11025,"code":11026,"language":27,"meta":28},[25],"11 字节读取完成\n↓\non_read()\n↓\n回调结束\n↓\n没有新的异步任务\n↓\nio.run() 返回\n↓\n程序结束\n",[30,11028,11026],{"__ignoreMap":28},[40,11030],{},[55,11032,3949,11034,3258,11036,11039],{"id":11033},"为什么-serial_-和-buffer_-要做成成员变量",[30,11035,7890],{},[30,11037,11038],{},"buffer_"," 要做成成员变量？",[15,11041,5703],{},[22,11043,11045],{"className":210,"code":11044,"language":212,"meta":28,"style":28},"boost::asio::serial_port serial_;\nstd::array\u003Cchar, 11> buffer_{};\n",[30,11046,11047,11057],{"__ignoreMap":28},[70,11048,11049,11051,11053,11055],{"class":72,"line":73},[70,11050,540],{"class":76},[70,11052,386],{"class":264},[70,11054,389],{"class":76},[70,11056,8718],{"class":264},[70,11058,11059,11061,11063,11065,11067,11069,11071],{"class":72,"line":133},[70,11060,2058],{"class":76},[70,11062,1623],{"class":264},[70,11064,1626],{"class":219},[70,11066,274],{"class":264},[70,11068,1631],{"class":124},[70,11070,1634],{"class":219},[70,11072,10549],{"class":264},[15,11074,11075],{},"都是：",[22,11077,11080],{"className":11078,"code":11079,"language":27,"meta":28},[25],"SerialReader 对象的成员变量\n",[30,11081,11079],{"__ignoreMap":28},[15,11083,11084],{},"因此只要：",[22,11086,11088],{"className":210,"code":11087,"language":212,"meta":28,"style":28},"SerialReader reader\n",[30,11089,11090],{"__ignoreMap":28},[70,11091,11092],{"class":72,"line":73},[70,11093,11087],{"class":264},[15,11095,11096],{},"还存在：",[22,11098,11101],{"className":11099,"code":11100,"language":27,"meta":28},[25],"serial_\nbuffer_\n",[30,11102,11100],{"__ignoreMap":28},[15,11104,11105],{},"就一直存在。",[15,11107,11108],{},"这很适合异步操作。",[15,11110,2048],{},[22,11112,11114],{"className":210,"code":11113,"language":212,"meta":28,"style":28},"boost::asio::async_read(\n    serial_,\n    boost::asio::buffer(buffer_),\n    ...);\n",[30,11115,11116,11130,11135,11149],{"__ignoreMap":28},[70,11117,11118,11120,11122,11124,11126,11128],{"class":72,"line":73},[70,11119,540],{"class":76},[70,11121,386],{"class":264},[70,11123,389],{"class":76},[70,11125,386],{"class":264},[70,11127,6084],{"class":76},[70,11129,620],{"class":264},[70,11131,11132],{"class":72,"line":133},[70,11133,11134],{"class":264},"    serial_,\n",[70,11136,11137,11139,11141,11143,11145,11147],{"class":72,"line":141},[70,11138,383],{"class":76},[70,11140,386],{"class":264},[70,11142,389],{"class":76},[70,11144,386],{"class":264},[70,11146,810],{"class":76},[70,11148,10277],{"class":264},[70,11150,11151],{"class":72,"line":240},[70,11152,5769],{"class":264},[15,11154,11155],{},"注册完成以后：",[22,11157,11160],{"className":11158,"code":11159,"language":27,"meta":28},[25],"async_read() 已经返回\n",[30,11161,11159],{"__ignoreMap":28},[15,11163,11164],{},"但是 Asio 之后仍然需要继续使用：",[22,11166,11167],{"className":210,"code":11100,"language":212,"meta":28,"style":28},[30,11168,11169,11174],{"__ignoreMap":28},[70,11170,11171],{"class":72,"line":73},[70,11172,11173],{"class":264},"serial_\n",[70,11175,11176],{"class":72,"line":133},[70,11177,11178],{"class":264},"buffer_\n",[15,11180,11181],{},"如果 buffer 是一个很快被销毁的局部变量：",[22,11183,11185],{"className":210,"code":11184,"language":212,"meta":28,"style":28},"void start_read()\n{\n    std::array\u003Cchar, 11> buffer{};\n\n    boost::asio::async_read(\n        serial_,\n        boost::asio::buffer(buffer),\n        ...);\n}\n",[30,11186,11187,11195,11199,11215,11219,11233,11237,11251,11255],{"__ignoreMap":28},[70,11188,11189,11191,11193],{"class":72,"line":73},[70,11190,4525],{"class":219},[70,11192,10217],{"class":76},[70,11194,3162],{"class":264},[70,11196,11197],{"class":72,"line":133},[70,11198,289],{"class":264},[70,11200,11201,11203,11205,11207,11209,11211,11213],{"class":72,"line":141},[70,11202,302],{"class":76},[70,11204,1623],{"class":264},[70,11206,1626],{"class":219},[70,11208,274],{"class":264},[70,11210,1631],{"class":124},[70,11212,1634],{"class":219},[70,11214,1637],{"class":264},[70,11216,11217],{"class":72,"line":240},[70,11218,252],{"emptyLinePlaceholder":251},[70,11220,11221,11223,11225,11227,11229,11231],{"class":72,"line":248},[70,11222,383],{"class":76},[70,11224,386],{"class":264},[70,11226,389],{"class":76},[70,11228,386],{"class":264},[70,11230,6084],{"class":76},[70,11232,620],{"class":264},[70,11234,11235],{"class":72,"line":255},[70,11236,9500],{"class":264},[70,11238,11239,11241,11243,11245,11247,11249],{"class":72,"line":286},[70,11240,626],{"class":76},[70,11242,386],{"class":264},[70,11244,389],{"class":76},[70,11246,386],{"class":264},[70,11248,810],{"class":76},[70,11250,1727],{"class":264},[70,11252,11253],{"class":72,"line":292},[70,11254,9519],{"class":264},[70,11256,11257],{"class":72,"line":299},[70,11258,920],{"class":264},[15,11260,11261],{},"那么：",[22,11263,11266],{"className":11264,"code":11265,"language":27,"meta":28},[25],"start_read() 返回\n↓\n局部 buffer 被销毁\n↓\n异步读取还没完成\n↓\nAsio 使用的内存失效\n",[30,11267,11265],{"__ignoreMap":28},[15,11269,11270],{},"所以类封装异步 I\u002FO 时，经常把：",[22,11272,11275],{"className":11273,"code":11274,"language":27,"meta":28},[25],"I\u002FO 对象\nbuffer\n状态\n队列\n",[30,11276,11274],{"__ignoreMap":28},[15,11278,11279],{},"都保存成成员变量。",[40,11281],{},[55,11283,11285,11286,11288],{"id":11284},"为什么下一次读取会覆盖上一次的-buffer_","为什么下一次读取会覆盖上一次的 ",[30,11287,11038],{},"？",[15,11290,11291],{},"本例始终使用同一个：",[22,11293,11295],{"className":210,"code":11294,"language":212,"meta":28,"style":28},"std::array\u003Cchar, 11> buffer_{};\n",[30,11296,11297],{"__ignoreMap":28},[70,11298,11299,11301,11303,11305,11307,11309,11311],{"class":72,"line":73},[70,11300,2058],{"class":76},[70,11302,1623],{"class":264},[70,11304,1626],{"class":219},[70,11306,274],{"class":264},[70,11308,1631],{"class":124},[70,11310,1634],{"class":219},[70,11312,10549],{"class":264},[15,11314,11315],{},"第一次读取：",[22,11317,11320],{"className":11318,"code":11319,"language":27,"meta":28},[25],"buffer_\n\nhello asio\\n\n",[30,11321,11319],{"__ignoreMap":28},[15,11323,11324],{},"进入：",[22,11326,11327],{"className":210,"code":7289,"language":212,"meta":28,"style":28},[30,11328,11329],{"__ignoreMap":28},[70,11330,11331,11333],{"class":72,"line":73},[70,11332,7296],{"class":76},[70,11334,3162],{"class":264},[15,11336,11337],{},"以后，我们先：",[22,11339,11341],{"className":210,"code":11340,"language":212,"meta":28,"style":28},"std::string msg(\n    buffer_.data(),\n    bytes_transferred);\n",[30,11342,11343,11355,11366],{"__ignoreMap":28},[70,11344,11345,11347,11349,11351,11353],{"class":72,"line":73},[70,11346,2058],{"class":76},[70,11348,386],{"class":264},[70,11350,3196],{"class":76},[70,11352,3199],{"class":76},[70,11354,620],{"class":264},[70,11356,11357,11360,11362,11364],{"class":72,"line":133},[70,11358,11359],{"class":76},"    buffer_",[70,11361,3206],{"class":264},[70,11363,1812],{"class":76},[70,11365,6310],{"class":264},[70,11367,11368,11371],{"class":72,"line":141},[70,11369,11370],{"class":76},"    bytes_transferred",[70,11372,898],{"class":264},[15,11374,11375],{},"把当前数据复制到：",[22,11377,11378],{"className":210,"code":5811,"language":212,"meta":28,"style":28},[30,11379,11380],{"__ignoreMap":28},[70,11381,11382],{"class":72,"line":73},[70,11383,5811],{"class":264},[15,11385,11386],{},"然后处理。",[15,11388,11389],{},"处理完成后：",[22,11391,11392],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,11393,11394],{"__ignoreMap":28},[70,11395,11396,11398],{"class":72,"line":73},[70,11397,9753],{"class":76},[70,11399,2240],{"class":264},[15,11401,11402],{},"再次：",[22,11404,11405],{"className":210,"code":11113,"language":212,"meta":28,"style":28},[30,11406,11407,11421,11425,11439],{"__ignoreMap":28},[70,11408,11409,11411,11413,11415,11417,11419],{"class":72,"line":73},[70,11410,540],{"class":76},[70,11412,386],{"class":264},[70,11414,389],{"class":76},[70,11416,386],{"class":264},[70,11418,6084],{"class":76},[70,11420,620],{"class":264},[70,11422,11423],{"class":72,"line":133},[70,11424,11134],{"class":264},[70,11426,11427,11429,11431,11433,11435,11437],{"class":72,"line":141},[70,11428,383],{"class":76},[70,11430,386],{"class":264},[70,11432,389],{"class":76},[70,11434,386],{"class":264},[70,11436,810],{"class":76},[70,11438,10277],{"class":264},[70,11440,11441],{"class":72,"line":240},[70,11442,5769],{"class":264},[15,11444,11445],{},"下一组数据仍然从：",[22,11447,11449],{"className":210,"code":11448,"language":212,"meta":28,"style":28},"buffer_[0]\n",[30,11450,11451],{"__ignoreMap":28},[70,11452,11453,11456,11458],{"class":72,"line":73},[70,11454,11455],{"class":264},"buffer_[",[70,11457,2485],{"class":124},[70,11459,2488],{"class":264},[15,11461,2491],{},[15,11463,2160],{},[22,11465,11468],{"className":11466,"code":11467,"language":27,"meta":28},[25],"第一次：\n\nbuffer_\n↓\nhello asio\\n\n",[30,11469,11467],{"__ignoreMap":28},[15,11471,11472],{},"下一次：",[22,11474,11477],{"className":11475,"code":11476,"language":27,"meta":28},[25],"buffer_\n↓\nserial c++\\n\n",[30,11478,11476],{"__ignoreMap":28},[15,11480,11481],{},"旧内容会被覆盖。",[15,11483,11484],{},"这没有问题，因为：",[22,11486,11489],{"className":11487,"code":11488,"language":27,"meta":28},[25],"上一组数据已经在 on_read() 中处理完成\n↓\n才重新启动下一次读取\n",[30,11490,11488],{"__ignoreMap":28},[40,11492],{},[55,11494,11496,11497,11288],{"id":11495},"为什么这里不会出现两个读取同时修改-buffer_","为什么这里不会出现两个读取同时修改 ",[30,11498,11038],{},[15,11500,2048],{},[22,11502,11503],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,11504,11505],{"__ignoreMap":28},[70,11506,11507,11509],{"class":72,"line":73},[70,11508,9753],{"class":76},[70,11510,2240],{"class":264},[15,11512,11513],{},"不是不停地连续调用很多次。",[15,11515,6012],{},[22,11517,11520],{"className":11518,"code":11519,"language":27,"meta":28},[25],"第一次 async_read()\n↓\n等待完成\n↓\non_read()\n↓\n当前读取已经结束\n↓\n才 start_read()\n↓\n注册下一次 async_read()\n",[30,11521,11519],{"__ignoreMap":28},[15,11523,11524],{},"所以任何时刻只有：",[22,11526,11529],{"className":11527,"code":11528,"language":27,"meta":28},[25],"一个 async_read()\n",[30,11530,11528],{"__ignoreMap":28},[15,11532,11533],{},"正在使用：",[22,11535,11536],{"className":210,"code":11178,"language":212,"meta":28,"style":28},[30,11537,11538],{"__ignoreMap":28},[70,11539,11540],{"class":72,"line":73},[70,11541,11178],{"class":264},[15,11543,11544],{},"流程严格是：",[22,11546,11549],{"className":11547,"code":11548,"language":27,"meta":28},[25],"读取 1\n↓\n完成\n\n读取 2\n↓\n完成\n\n读取 3\n↓\n完成\n",[30,11550,11548],{"__ignoreMap":28},[15,11552,9614],{},[22,11554,11557],{"className":11555,"code":11556,"language":27,"meta":28},[25],"读取 1 ────────┐\n读取 2 ────────┼→ 同时操作 buffer_\n读取 3 ────────┘\n",[30,11558,11556],{"__ignoreMap":28},[40,11560],{},[55,11562,11564,11565],{"id":11563},"成员函数的-stdbind","成员函数的 ",[30,11566,37],{},[15,11568,5703],{},[22,11570,11572],{"className":210,"code":11571,"language":212,"meta":28,"style":28},"std::bind(\n    &SerialReader::on_read,\n    this,\n    std::placeholders::_1,\n    std::placeholders::_2)\n",[30,11573,11574,11584,11592,11599,11609],{"__ignoreMap":28},[70,11575,11576,11578,11580,11582],{"class":72,"line":73},[70,11577,2058],{"class":76},[70,11579,386],{"class":264},[70,11581,5144],{"class":76},[70,11583,620],{"class":264},[70,11585,11586,11588,11590],{"class":72,"line":133},[70,11587,7407],{"class":219},[70,11589,10294],{"class":76},[70,11591,10297],{"class":264},[70,11593,11594,11597],{"class":72,"line":141},[70,11595,11596],{"class":124},"    this",[70,11598,4555],{"class":264},[70,11600,11601,11603,11605,11607],{"class":72,"line":240},[70,11602,302],{"class":76},[70,11604,386],{"class":264},[70,11606,5161],{"class":76},[70,11608,5164],{"class":264},[70,11610,11611,11613,11615,11617],{"class":72,"line":248},[70,11612,302],{"class":76},[70,11614,386],{"class":264},[70,11616,5161],{"class":76},[70,11618,5684],{"class":264},[15,11620,3047],{},[22,11622,11624],{"className":210,"code":11623,"language":212,"meta":28,"style":28},"&SerialReader::on_read\n",[30,11625,11626],{"__ignoreMap":28},[70,11627,11628,11630,11632],{"class":72,"line":73},[70,11629,4549],{"class":219},[70,11631,10294],{"class":76},[70,11633,11634],{"class":264},"::on_read\n",[15,11636,2203],{},[22,11638,11641],{"className":11639,"code":11640,"language":27,"meta":28},[25],"要调用 SerialReader 的成员函数 on_read()\n",[30,11642,11640],{"__ignoreMap":28},[22,11644,11646],{"className":210,"code":11645,"language":212,"meta":28,"style":28},"this\n",[30,11647,11648],{"__ignoreMap":28},[70,11649,11650],{"class":72,"line":73},[70,11651,11645],{"class":124},[15,11653,2203],{},[22,11655,11658],{"className":11656,"code":11657,"language":27,"meta":28},[25],"对当前这个 SerialReader 对象调用\n",[30,11659,11657],{"__ignoreMap":28},[15,11661,11662],{},"两个占位符：",[22,11664,11666],{"className":11665,"code":5690,"language":27,"meta":28},[25],[30,11667,5690],{"__ignoreMap":28},[15,11669,11670],{},"所以异步读取完成以后，相当于：",[22,11672,11674],{"className":210,"code":11673,"language":212,"meta":28,"style":28},"this->on_read(\n    ec,\n    bytes_transferred);\n",[30,11675,11676,11688,11692],{"__ignoreMap":28},[70,11677,11678,11681,11684,11686],{"class":72,"line":73},[70,11679,11680],{"class":124},"this",[70,11682,11683],{"class":264},"->",[70,11685,7296],{"class":76},[70,11687,620],{"class":264},[70,11689,11690],{"class":72,"line":133},[70,11691,7429],{"class":264},[70,11693,11694],{"class":72,"line":141},[70,11695,11696],{"class":264},"    bytes_transferred);\n",[40,11698],{},[55,11700,11702],{"id":11701},"示例-4-和示例-6-的区别","示例 4 和示例 6 的区别",[15,11704,11705],{},"示例 4：",[22,11707,11710],{"className":11708,"code":11709,"language":27,"meta":28},[25],"注册一次 async_read()\n↓\n读取一次\n↓\n回调一次\n↓\n结束\n",[30,11711,11709],{"__ignoreMap":28},[15,11713,11714],{},"示例 6：",[22,11716,11719],{"className":11717,"code":11718,"language":27,"meta":28},[25],"start_read()\n↓\nasync_read()\n↓\non_read()\n↓\nstart_read()\n↓\nasync_read()\n↓\non_read()\n↓\n...\n",[30,11720,11718],{"__ignoreMap":28},[15,11722,2160],{},[22,11724,11727],{"className":11725,"code":11726,"language":27,"meta":28},[25],"示例 4\n→ 学习一次异步读取是怎么工作的\n\n示例 6\n→ 学习怎样把异步读取封装进类并持续运行\n",[30,11728,11726],{"__ignoreMap":28},[15,11730,3227],{},[12,11732,11733],{},[15,11734,11735],{},"连续异步读取的核心不是写一个死循环，而是在一次异步读取完成的回调里，再注册下一次异步读取。",[40,11737],{},[43,11739,11741],{"id":11740},"示例-7类里同时封装异步串口发送和接收","示例 7：类里同时封装异步串口发送和接收",[55,11743,186],{"id":11744},"程序目标-6",[15,11746,11747],{},"前面的两个示例分别完成了：",[22,11749,11752],{"className":11750,"code":11751,"language":27,"meta":28},[25],"示例 5：\n异步发送队列\n\n示例 6：\n连续异步接收\n",[30,11753,11751],{"__ignoreMap":28},[15,11755,11756],{},"这一节把它们合并到同一个类中。",[15,11758,11759],{},"最终得到：",[22,11761,11764],{"className":11762,"code":11763,"language":27,"meta":28},[25],"AsyncSerialPort\n│\n├── 接收\n│   │\n│   ├── start_read()\n│   ├── async_read()\n│   └── on_read()\n│        ↓\n│      再次 start_read()\n│\n└── 发送\n    │\n    ├── async_send()\n    ├── write_queue_\n    ├── do_write()\n    └── on_write()\n         ↓\n       继续发送队首\n",[30,11765,11763],{"__ignoreMap":28},[15,11767,11768],{},"这个类可以：",[22,11770,11773],{"className":11771,"code":11772,"language":27,"meta":28},[25],"一边持续接收串口数据\n\n同时\n\n一边异步发送串口数据\n",[30,11774,11772],{"__ignoreMap":28},[15,11776,11777],{},"本示例仍然只有：",[22,11779,11782],{"className":11780,"code":11781,"language":27,"meta":28},[25],"一个线程调用 io.run()\n",[30,11783,11781],{"__ignoreMap":28},[15,11785,11786],{},"所以暂时不涉及多线程并发问题。",[55,11788,207],{"id":11789},"完整代码-6",[22,11791,11793],{"className":210,"code":11792,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Carray>\n#include \u003Cdeque>\n#include \u003Cfunctional>\n#include \u003Cprint>\n#include \u003Cstring>\n\nclass AsyncSerialPort\n{\npublic:\n    AsyncSerialPort(\n        boost::asio::io_context& io,\n        const std::string& port_name)\n        : serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n\n        if (ec)\n        {\n            std::println(\n                \"打开串口失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        serial_.set_option(\n            boost::asio::serial_port_base::baud_rate(115200));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::character_size(8));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::parity(\n                boost::asio::serial_port_base::parity::none));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::stop_bits(\n                boost::asio::serial_port_base::stop_bits::one));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::flow_control(\n                boost::asio::serial_port_base::flow_control::none));\n\n        std::println(\n            \"AsyncSerialPort：串口打开成功\");\n\n        \u002F\u002F 注册第一次异步读取。\n        start_read();\n    }\n\n    void async_send(const std::string& msg)\n    {\n        \u002F\u002F 队列原来非空，说明已经有数据正在发送，\n        \u002F\u002F 或者已经有其他数据正在排队。\n        bool writing = !write_queue_.empty();\n\n        \u002F\u002F 保存发送数据，保证异步写期间内存一直存在。\n        write_queue_.push_back(msg);\n\n        std::print(\n            \"加入发送队列：{}\",\n            msg);\n\n        \u002F\u002F 如果原来没有正在发送的数据，\n        \u002F\u002F 就从当前队首开始整个发送流程。\n        if (!writing)\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    void start_read()\n    {\n        std::println(\n            \"AsyncSerialPort：等待接收下一组 11 字节\");\n\n        boost::asio::async_read(\n            serial_,\n            boost::asio::buffer(read_buffer_),\n            std::bind(\n                &AsyncSerialPort::on_read,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_read(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"读取失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::string msg(\n            read_buffer_.data(),\n            bytes_transferred);\n\n        std::println(\n            \"收到数据，字节数 = {}，内容 = {}\",\n            bytes_transferred,\n            msg);\n\n        \u002F\u002F 当前这一组数据处理完成以后，\n        \u002F\u002F 再注册下一次异步读取。\n        start_read();\n    }\n\n    void do_write()\n    {\n        boost::asio::async_write(\n            serial_,\n            boost::asio::buffer(\n                write_queue_.front()),\n            std::bind(\n                &AsyncSerialPort::on_write,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_write(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"发送失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::println(\n            \"发送完成，字节数 = {}\",\n            bytes_transferred);\n\n        \u002F\u002F 当前队首已经发送完成。\n        write_queue_.pop_front();\n\n        \u002F\u002F 如果队列还有数据，继续发送新的队首。\n        if (!write_queue_.empty())\n        {\n            do_write();\n        }\n    }\n\nprivate:\n    boost::asio::serial_port serial_;\n\n    \u002F\u002F 每次固定读取 11 个字节。\n    std::array\u003Cchar, 11> read_buffer_{};\n\n    \u002F\u002F 保存正在发送以及等待发送的数据。\n    std::deque\u003Cstd::string> write_queue_;\n};\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    AsyncSerialPort serial(io, port_name);\n\n    \u002F\u002F 先注册几条异步发送任务。\n    serial.async_send(\"message one\\n\");\n    serial.async_send(\"message two\\n\");\n    serial.async_send(\"message three\\n\");\n\n    std::println(\n        \"main：开始 io.run()，按 Ctrl+C 结束程序\");\n\n    io.run();\n\n    std::println(\"main：io.run() 返回\");\n\n    return 0;\n}\n",[30,11794,11795,11801,11807,11813,11819,11825,11831,11837,11841,11848,11852,11856,11863,11881,11897,11905,11909,11919,11923,11931,11935,11941,11945,11955,11961,11969,11973,11979,11983,11987,11995,12017,12021,12029,12051,12055,12063,12081,12099,12103,12111,12129,12147,12151,12159,12177,12195,12199,12209,12216,12220,12225,12231,12235,12239,12261,12265,12270,12275,12291,12295,12300,12308,12312,12322,12328,12332,12336,12341,12346,12356,12360,12366,12370,12374,12378,12382,12390,12394,12404,12411,12415,12429,12433,12448,12458,12467,12473,12483,12493,12497,12501,12509,12529,12541,12545,12551,12555,12565,12572,12580,12584,12590,12594,12598,12608,12617,12621,12625,12635,12641,12645,12649,12653,12658,12662,12668,12672,12676,12684,12688,12702,12706,12720,12728,12738,12746,12752,12762,12772,12776,12780,12788,12808,12820,12824,12830,12834,12844,12850,12858,12862,12868,12872,12876,12886,12892,12897,12902,12908,12917,12922,12928,12943,12948,12955,12960,12965,12970,12975,12986,12991,12996,13014,13019,13025,13042,13047,13052,13073,13078,13091,13096,13109,13114,13127,13132,13137,13148,13153,13163,13168,13174,13191,13208,13225,13230,13241,13249,13254,13263,13268,13283,13288,13297],{"__ignoreMap":28},[70,11796,11797,11799],{"class":72,"line":73},[70,11798,220],{"class":219},[70,11800,223],{"class":80},[70,11802,11803,11805],{"class":72,"line":133},[70,11804,220],{"class":219},[70,11806,230],{"class":80},[70,11808,11809,11811],{"class":72,"line":141},[70,11810,220],{"class":219},[70,11812,1172],{"class":80},[70,11814,11815,11817],{"class":72,"line":240},[70,11816,220],{"class":219},[70,11818,7797],{"class":80},[70,11820,11821,11823],{"class":72,"line":248},[70,11822,220],{"class":219},[70,11824,4504],{"class":80},[70,11826,11827,11829],{"class":72,"line":255},[70,11828,220],{"class":219},[70,11830,237],{"class":80},[70,11832,11833,11835],{"class":72,"line":286},[70,11834,220],{"class":219},[70,11836,245],{"class":80},[70,11838,11839],{"class":72,"line":292},[70,11840,252],{"emptyLinePlaceholder":251},[70,11842,11843,11845],{"class":72,"line":299},[70,11844,7824],{"class":219},[70,11846,11847],{"class":76}," AsyncSerialPort\n",[70,11849,11850],{"class":72,"line":317},[70,11851,289],{"class":264},[70,11853,11854],{"class":72,"line":322},[70,11855,7836],{"class":219},[70,11857,11858,11861],{"class":72,"line":340},[70,11859,11860],{"class":76},"    AsyncSerialPort",[70,11862,620],{"class":264},[70,11864,11865,11867,11869,11871,11873,11875,11877,11879],{"class":72,"line":346},[70,11866,626],{"class":76},[70,11868,386],{"class":264},[70,11870,389],{"class":76},[70,11872,386],{"class":264},[70,11874,7856],{"class":76},[70,11876,4549],{"class":219},[70,11878,7861],{"class":270},[70,11880,4555],{"class":264},[70,11882,11883,11885,11887,11889,11891,11893,11895],{"class":72,"line":363},[70,11884,7868],{"class":219},[70,11886,7871],{"class":76},[70,11888,386],{"class":264},[70,11890,3196],{"class":76},[70,11892,4549],{"class":219},[70,11894,7880],{"class":270},[70,11896,337],{"class":264},[70,11898,11899,11901,11903],{"class":72,"line":369},[70,11900,7887],{"class":264},[70,11902,7890],{"class":76},[70,11904,7893],{"class":264},[70,11906,11907],{"class":72,"line":374},[70,11908,343],{"class":264},[70,11910,11911,11913,11915,11917],{"class":72,"line":380},[70,11912,626],{"class":76},[70,11914,386],{"class":264},[70,11916,426],{"class":76},[70,11918,429],{"class":264},[70,11920,11921],{"class":72,"line":395},[70,11922,252],{"emptyLinePlaceholder":251},[70,11924,11925,11927,11929],{"class":72,"line":401},[70,11926,7916],{"class":264},[70,11928,466],{"class":76},[70,11930,469],{"class":264},[70,11932,11933],{"class":72,"line":419},[70,11934,252],{"emptyLinePlaceholder":251},[70,11936,11937,11939],{"class":72,"line":432},[70,11938,7929],{"class":219},[70,11940,477],{"class":264},[70,11942,11943],{"class":72,"line":437},[70,11944,7936],{"class":264},[70,11946,11947,11949,11951,11953],{"class":72,"line":455},[70,11948,5156],{"class":76},[70,11950,386],{"class":264},[70,11952,444],{"class":76},[70,11954,620],{"class":264},[70,11956,11957,11959],{"class":72,"line":460},[70,11958,7951],{"class":80},[70,11960,4555],{"class":264},[70,11962,11963,11965,11967],{"class":72,"line":472},[70,11964,7958],{"class":264},[70,11966,503],{"class":76},[70,11968,506],{"class":264},[70,11970,11971],{"class":72,"line":480},[70,11972,252],{"emptyLinePlaceholder":251},[70,11974,11975,11977],{"class":72,"line":485},[70,11976,7971],{"class":219},[70,11978,314],{"class":264},[70,11980,11981],{"class":72,"line":509},[70,11982,7978],{"class":264},[70,11984,11985],{"class":72,"line":520},[70,11986,252],{"emptyLinePlaceholder":251},[70,11988,11989,11991,11993],{"class":72,"line":525},[70,11990,7916],{"class":264},[70,11992,535],{"class":76},[70,11994,620],{"class":264},[70,11996,11997,11999,12001,12003,12005,12007,12009,12011,12013,12015],{"class":72,"line":530},[70,11998,1496],{"class":76},[70,12000,386],{"class":264},[70,12002,389],{"class":76},[70,12004,386],{"class":264},[70,12006,549],{"class":76},[70,12008,386],{"class":264},[70,12010,554],{"class":76},[70,12012,265],{"class":264},[70,12014,559],{"class":124},[70,12016,562],{"class":264},[70,12018,12019],{"class":72,"line":565},[70,12020,252],{"emptyLinePlaceholder":251},[70,12022,12023,12025,12027],{"class":72,"line":596},[70,12024,7916],{"class":264},[70,12026,535],{"class":76},[70,12028,620],{"class":264},[70,12030,12031,12033,12035,12037,12039,12041,12043,12045,12047,12049],{"class":72,"line":623},[70,12032,1496],{"class":76},[70,12034,386],{"class":264},[70,12036,389],{"class":76},[70,12038,386],{"class":264},[70,12040,549],{"class":76},[70,12042,386],{"class":264},[70,12044,586],{"class":76},[70,12046,265],{"class":264},[70,12048,591],{"class":124},[70,12050,562],{"class":264},[70,12052,12053],{"class":72,"line":644},[70,12054,252],{"emptyLinePlaceholder":251},[70,12056,12057,12059,12061],{"class":72,"line":670},[70,12058,7916],{"class":264},[70,12060,535],{"class":76},[70,12062,620],{"class":264},[70,12064,12065,12067,12069,12071,12073,12075,12077,12079],{"class":72,"line":690},[70,12066,1496],{"class":76},[70,12068,386],{"class":264},[70,12070,389],{"class":76},[70,12072,386],{"class":264},[70,12074,549],{"class":76},[70,12076,386],{"class":264},[70,12078,617],{"class":76},[70,12080,620],{"class":264},[70,12082,12083,12085,12087,12089,12091,12093,12095,12097],{"class":72,"line":716},[70,12084,8081],{"class":76},[70,12086,386],{"class":264},[70,12088,389],{"class":76},[70,12090,386],{"class":264},[70,12092,549],{"class":76},[70,12094,386],{"class":264},[70,12096,617],{"class":76},[70,12098,641],{"class":264},[70,12100,12101],{"class":72,"line":735},[70,12102,252],{"emptyLinePlaceholder":251},[70,12104,12105,12107,12109],{"class":72,"line":740},[70,12106,7916],{"class":264},[70,12108,535],{"class":76},[70,12110,620],{"class":264},[70,12112,12113,12115,12117,12119,12121,12123,12125,12127],{"class":72,"line":761},[70,12114,1496],{"class":76},[70,12116,386],{"class":264},[70,12118,389],{"class":76},[70,12120,386],{"class":264},[70,12122,549],{"class":76},[70,12124,386],{"class":264},[70,12126,665],{"class":76},[70,12128,620],{"class":264},[70,12130,12131,12133,12135,12137,12139,12141,12143,12145],{"class":72,"line":766},[70,12132,8081],{"class":76},[70,12134,386],{"class":264},[70,12136,389],{"class":76},[70,12138,386],{"class":264},[70,12140,549],{"class":76},[70,12142,386],{"class":264},[70,12144,665],{"class":76},[70,12146,687],{"class":264},[70,12148,12149],{"class":72,"line":772},[70,12150,252],{"emptyLinePlaceholder":251},[70,12152,12153,12155,12157],{"class":72,"line":816},[70,12154,7916],{"class":264},[70,12156,535],{"class":76},[70,12158,620],{"class":264},[70,12160,12161,12163,12165,12167,12169,12171,12173,12175],{"class":72,"line":823},[70,12162,1496],{"class":76},[70,12164,386],{"class":264},[70,12166,389],{"class":76},[70,12168,386],{"class":264},[70,12170,549],{"class":76},[70,12172,386],{"class":264},[70,12174,711],{"class":76},[70,12176,620],{"class":264},[70,12178,12179,12181,12183,12185,12187,12189,12191,12193],{"class":72,"line":828},[70,12180,8081],{"class":76},[70,12182,386],{"class":264},[70,12184,389],{"class":76},[70,12186,386],{"class":264},[70,12188,549],{"class":76},[70,12190,386],{"class":264},[70,12192,711],{"class":76},[70,12194,641],{"class":264},[70,12196,12197],{"class":72,"line":848},[70,12198,252],{"emptyLinePlaceholder":251},[70,12200,12201,12203,12205,12207],{"class":72,"line":857},[70,12202,488],{"class":76},[70,12204,386],{"class":264},[70,12206,444],{"class":76},[70,12208,620],{"class":264},[70,12210,12211,12214],{"class":72,"line":862},[70,12212,12213],{"class":80},"            \"AsyncSerialPort：串口打开成功\"",[70,12215,898],{"class":264},[70,12217,12218],{"class":72,"line":867},[70,12219,252],{"emptyLinePlaceholder":251},[70,12221,12222],{"class":72,"line":884},[70,12223,12224],{"class":295},"        \u002F\u002F 注册第一次异步读取。\n",[70,12226,12227,12229],{"class":72,"line":901},[70,12228,10196],{"class":76},[70,12230,2240],{"class":264},[70,12232,12233],{"class":72,"line":906},[70,12234,366],{"class":264},[70,12236,12237],{"class":72,"line":917},[70,12238,252],{"emptyLinePlaceholder":251},[70,12240,12241,12243,12245,12247,12249,12251,12253,12255,12257,12259],{"class":72,"line":1618},[70,12242,8223],{"class":219},[70,12244,8226],{"class":76},[70,12246,265],{"class":264},[70,12248,5601],{"class":219},[70,12250,7871],{"class":76},[70,12252,386],{"class":264},[70,12254,3196],{"class":76},[70,12256,4549],{"class":219},[70,12258,3199],{"class":270},[70,12260,337],{"class":264},[70,12262,12263],{"class":72,"line":1640},[70,12264,343],{"class":264},[70,12266,12267],{"class":72,"line":1645},[70,12268,12269],{"class":295},"        \u002F\u002F 队列原来非空，说明已经有数据正在发送，\n",[70,12271,12272],{"class":72,"line":1661},[70,12273,12274],{"class":295},"        \u002F\u002F 或者已经有其他数据正在排队。\n",[70,12276,12277,12279,12281,12283,12285,12287,12289],{"class":72,"line":1666},[70,12278,8261],{"class":219},[70,12280,8264],{"class":264},[70,12282,308],{"class":219},[70,12284,8269],{"class":219},[70,12286,8272],{"class":264},[70,12288,8275],{"class":76},[70,12290,2240],{"class":264},[70,12292,12293],{"class":72,"line":1672},[70,12294,252],{"emptyLinePlaceholder":251},[70,12296,12297],{"class":72,"line":1678},[70,12298,12299],{"class":295},"        \u002F\u002F 保存发送数据，保证异步写期间内存一直存在。\n",[70,12301,12302,12304,12306],{"class":72,"line":1692},[70,12303,8296],{"class":264},[70,12305,8299],{"class":76},[70,12307,8302],{"class":264},[70,12309,12310],{"class":72,"line":1708},[70,12311,252],{"emptyLinePlaceholder":251},[70,12313,12314,12316,12318,12320],{"class":72,"line":1714},[70,12315,488],{"class":76},[70,12317,386],{"class":264},[70,12319,8315],{"class":76},[70,12321,620],{"class":264},[70,12323,12324,12326],{"class":72,"line":1730},[70,12325,8322],{"class":80},[70,12327,4555],{"class":264},[70,12329,12330],{"class":72,"line":1736},[70,12331,8329],{"class":264},[70,12333,12334],{"class":72,"line":1741},[70,12335,252],{"emptyLinePlaceholder":251},[70,12337,12338],{"class":72,"line":1748},[70,12339,12340],{"class":295},"        \u002F\u002F 如果原来没有正在发送的数据，\n",[70,12342,12343],{"class":72,"line":1753},[70,12344,12345],{"class":295},"        \u002F\u002F 就从当前队首开始整个发送流程。\n",[70,12347,12348,12350,12352,12354],{"class":72,"line":1773},[70,12349,7929],{"class":219},[70,12351,8350],{"class":264},[70,12353,8353],{"class":219},[70,12355,8356],{"class":264},[70,12357,12358],{"class":72,"line":1782},[70,12359,7936],{"class":264},[70,12361,12362,12364],{"class":72,"line":1787},[70,12363,8365],{"class":76},[70,12365,2240],{"class":264},[70,12367,12368],{"class":72,"line":1792},[70,12369,7978],{"class":264},[70,12371,12372],{"class":72,"line":1798},[70,12373,366],{"class":264},[70,12375,12376],{"class":72,"line":1818},[70,12377,252],{"emptyLinePlaceholder":251},[70,12379,12380],{"class":72,"line":1823},[70,12381,8384],{"class":219},[70,12383,12384,12386,12388],{"class":72,"line":1839},[70,12385,8223],{"class":219},[70,12387,10217],{"class":76},[70,12389,3162],{"class":264},[70,12391,12392],{"class":72,"line":1856},[70,12393,343],{"class":264},[70,12395,12396,12398,12400,12402],{"class":72,"line":1861},[70,12397,488],{"class":76},[70,12399,386],{"class":264},[70,12401,444],{"class":76},[70,12403,620],{"class":264},[70,12405,12406,12409],{"class":72,"line":1876},[70,12407,12408],{"class":80},"            \"AsyncSerialPort：等待接收下一组 11 字节\"",[70,12410,898],{"class":264},[70,12412,12413],{"class":72,"line":1881},[70,12414,252],{"emptyLinePlaceholder":251},[70,12416,12417,12419,12421,12423,12425,12427],{"class":72,"line":1890},[70,12418,626],{"class":76},[70,12420,386],{"class":264},[70,12422,389],{"class":76},[70,12424,386],{"class":264},[70,12426,6084],{"class":76},[70,12428,620],{"class":264},[70,12430,12431],{"class":72,"line":5216},[70,12432,8421],{"class":264},[70,12434,12435,12437,12439,12441,12443,12445],{"class":72,"line":5221},[70,12436,1496],{"class":76},[70,12438,386],{"class":264},[70,12440,389],{"class":76},[70,12442,386],{"class":264},[70,12444,810],{"class":76},[70,12446,12447],{"class":264},"(read_buffer_),\n",[70,12449,12450,12452,12454,12456],{"class":72,"line":5231},[70,12451,5156],{"class":76},[70,12453,386],{"class":264},[70,12455,5144],{"class":76},[70,12457,620],{"class":264},[70,12459,12460,12462,12465],{"class":72,"line":5236},[70,12461,8461],{"class":219},[70,12463,12464],{"class":76},"AsyncSerialPort",[70,12466,10297],{"class":264},[70,12468,12469,12471],{"class":72,"line":5252},[70,12470,8472],{"class":124},[70,12472,4555],{"class":264},[70,12474,12475,12477,12479,12481],{"class":72,"line":5267},[70,12476,8479],{"class":76},[70,12478,386],{"class":264},[70,12480,5161],{"class":76},[70,12482,5164],{"class":264},[70,12484,12485,12487,12489,12491],{"class":72,"line":5272},[70,12486,8479],{"class":76},[70,12488,386],{"class":264},[70,12490,5161],{"class":76},[70,12492,5175],{"class":264},[70,12494,12495],{"class":72,"line":5281},[70,12496,366],{"class":264},[70,12498,12499],{"class":72,"line":6936},[70,12500,252],{"emptyLinePlaceholder":251},[70,12502,12503,12505,12507],{"class":72,"line":6941},[70,12504,8223],{"class":219},[70,12506,6181],{"class":76},[70,12508,620],{"class":264},[70,12510,12511,12513,12515,12517,12519,12521,12523,12525,12527],{"class":72,"line":6950},[70,12512,7868],{"class":219},[70,12514,787],{"class":76},[70,12516,386],{"class":264},[70,12518,426],{"class":76},[70,12520,386],{"class":264},[70,12522,4546],{"class":76},[70,12524,4549],{"class":219},[70,12526,4552],{"class":270},[70,12528,4555],{"class":264},[70,12530,12531,12533,12535,12537,12539],{"class":72,"line":6955},[70,12532,488],{"class":76},[70,12534,386],{"class":264},[70,12536,779],{"class":219},[70,12538,4566],{"class":270},[70,12540,337],{"class":264},[70,12542,12543],{"class":72,"line":6970},[70,12544,343],{"class":264},[70,12546,12547,12549],{"class":72,"line":6985},[70,12548,7929],{"class":219},[70,12550,477],{"class":264},[70,12552,12553],{"class":72,"line":6990},[70,12554,7936],{"class":264},[70,12556,12557,12559,12561,12563],{"class":72,"line":6999},[70,12558,5156],{"class":76},[70,12560,386],{"class":264},[70,12562,444],{"class":76},[70,12564,620],{"class":264},[70,12566,12567,12570],{"class":72,"line":8599},[70,12568,12569],{"class":80},"                \"读取失败：{}\"",[70,12571,4555],{"class":264},[70,12573,12574,12576,12578],{"class":72,"line":8604},[70,12575,7958],{"class":264},[70,12577,503],{"class":76},[70,12579,506],{"class":264},[70,12581,12582],{"class":72,"line":8615},[70,12583,252],{"emptyLinePlaceholder":251},[70,12585,12586,12588],{"class":72,"line":8623},[70,12587,7971],{"class":219},[70,12589,314],{"class":264},[70,12591,12592],{"class":72,"line":8629},[70,12593,7978],{"class":264},[70,12595,12596],{"class":72,"line":8634},[70,12597,252],{"emptyLinePlaceholder":251},[70,12599,12600,12602,12604,12606],{"class":72,"line":8640},[70,12601,488],{"class":76},[70,12603,1803],{"class":264},[70,12605,1806],{"class":76},[70,12607,620],{"class":264},[70,12609,12610,12613,12615],{"class":72,"line":8650},[70,12611,12612],{"class":264},"            read_buffer_.",[70,12614,1812],{"class":76},[70,12616,6310],{"class":264},[70,12618,12619],{"class":72,"line":8655},[70,12620,8626],{"class":264},[70,12622,12623],{"class":72,"line":8661},[70,12624,252],{"emptyLinePlaceholder":251},[70,12626,12627,12629,12631,12633],{"class":72,"line":8677},[70,12628,488],{"class":76},[70,12630,386],{"class":264},[70,12632,444],{"class":76},[70,12634,620],{"class":264},[70,12636,12637,12639],{"class":72,"line":8682},[70,12638,10470],{"class":80},[70,12640,4555],{"class":264},[70,12642,12643],{"class":72,"line":8689},[70,12644,10477],{"class":264},[70,12646,12647],{"class":72,"line":8694},[70,12648,8329],{"class":264},[70,12650,12651],{"class":72,"line":8699},[70,12652,252],{"emptyLinePlaceholder":251},[70,12654,12655],{"class":72,"line":8704},[70,12656,12657],{"class":295},"        \u002F\u002F 当前这一组数据处理完成以后，\n",[70,12659,12660],{"class":72,"line":8709},[70,12661,10495],{"class":295},[70,12663,12664,12666],{"class":72,"line":8721},[70,12665,10196],{"class":76},[70,12667,2240],{"class":264},[70,12669,12670],{"class":72,"line":8726},[70,12671,366],{"class":264},[70,12673,12674],{"class":72,"line":8732},[70,12675,252],{"emptyLinePlaceholder":251},[70,12677,12678,12680,12682],{"class":72,"line":8752},[70,12679,8223],{"class":219},[70,12681,8391],{"class":76},[70,12683,3162],{"class":264},[70,12685,12686],{"class":72,"line":8758},[70,12687,343],{"class":264},[70,12689,12690,12692,12694,12696,12698,12700],{"class":72,"line":8763},[70,12691,626],{"class":76},[70,12693,386],{"class":264},[70,12695,389],{"class":76},[70,12697,386],{"class":264},[70,12699,4446],{"class":76},[70,12701,620],{"class":264},[70,12703,12704],{"class":72,"line":8784},[70,12705,8421],{"class":264},[70,12707,12708,12710,12712,12714,12716,12718],{"class":72,"line":8789},[70,12709,1496],{"class":76},[70,12711,386],{"class":264},[70,12713,389],{"class":76},[70,12715,386],{"class":264},[70,12717,810],{"class":76},[70,12719,620],{"class":264},[70,12721,12722,12724,12726],{"class":72,"line":8802},[70,12723,8440],{"class":264},[70,12725,8443],{"class":76},[70,12727,8446],{"class":264},[70,12729,12730,12732,12734,12736],{"class":72,"line":8807},[70,12731,5156],{"class":76},[70,12733,386],{"class":264},[70,12735,5144],{"class":76},[70,12737,620],{"class":264},[70,12739,12740,12742,12744],{"class":72,"line":8820},[70,12741,8461],{"class":219},[70,12743,12464],{"class":76},[70,12745,8467],{"class":264},[70,12747,12748,12750],{"class":72,"line":8825},[70,12749,8472],{"class":124},[70,12751,4555],{"class":264},[70,12753,12754,12756,12758,12760],{"class":72,"line":8838},[70,12755,8479],{"class":76},[70,12757,386],{"class":264},[70,12759,5161],{"class":76},[70,12761,5164],{"class":264},[70,12763,12764,12766,12768,12770],{"class":72,"line":8843},[70,12765,8479],{"class":76},[70,12767,386],{"class":264},[70,12769,5161],{"class":76},[70,12771,5175],{"class":264},[70,12773,12774],{"class":72,"line":8848},[70,12775,366],{"class":264},[70,12777,12778],{"class":72,"line":8859},[70,12779,252],{"emptyLinePlaceholder":251},[70,12781,12782,12784,12786],{"class":72,"line":8864},[70,12783,8223],{"class":219},[70,12785,4528],{"class":76},[70,12787,620],{"class":264},[70,12789,12790,12792,12794,12796,12798,12800,12802,12804,12806],{"class":72,"line":8876},[70,12791,7868],{"class":219},[70,12793,787],{"class":76},[70,12795,386],{"class":264},[70,12797,426],{"class":76},[70,12799,386],{"class":264},[70,12801,4546],{"class":76},[70,12803,4549],{"class":219},[70,12805,4552],{"class":270},[70,12807,4555],{"class":264},[70,12809,12810,12812,12814,12816,12818],{"class":72,"line":8881},[70,12811,488],{"class":76},[70,12813,386],{"class":264},[70,12815,779],{"class":219},[70,12817,4566],{"class":270},[70,12819,337],{"class":264},[70,12821,12822],{"class":72,"line":8899},[70,12823,343],{"class":264},[70,12825,12826,12828],{"class":72,"line":8916},[70,12827,7929],{"class":219},[70,12829,477],{"class":264},[70,12831,12832],{"class":72,"line":8933},[70,12833,7936],{"class":264},[70,12835,12836,12838,12840,12842],{"class":72,"line":8938},[70,12837,5156],{"class":76},[70,12839,386],{"class":264},[70,12841,444],{"class":76},[70,12843,620],{"class":264},[70,12845,12846,12848],{"class":72,"line":8953},[70,12847,8572],{"class":80},[70,12849,4555],{"class":264},[70,12851,12852,12854,12856],{"class":72,"line":8958},[70,12853,7958],{"class":264},[70,12855,503],{"class":76},[70,12857,506],{"class":264},[70,12859,12860],{"class":72,"line":8967},[70,12861,252],{"emptyLinePlaceholder":251},[70,12863,12864,12866],{"class":72,"line":8972},[70,12865,7971],{"class":219},[70,12867,314],{"class":264},[70,12869,12870],{"class":72,"line":8983},[70,12871,7978],{"class":264},[70,12873,12874],{"class":72,"line":8991},[70,12875,252],{"emptyLinePlaceholder":251},[70,12877,12878,12880,12882,12884],{"class":72,"line":8996},[70,12879,488],{"class":76},[70,12881,386],{"class":264},[70,12883,444],{"class":76},[70,12885,620],{"class":264},[70,12887,12888,12890],{"class":72,"line":9005},[70,12889,8618],{"class":80},[70,12891,4555],{"class":264},[70,12893,12895],{"class":72,"line":12894},147,[70,12896,8626],{"class":264},[70,12898,12900],{"class":72,"line":12899},148,[70,12901,252],{"emptyLinePlaceholder":251},[70,12903,12905],{"class":72,"line":12904},149,[70,12906,12907],{"class":295},"        \u002F\u002F 当前队首已经发送完成。\n",[70,12909,12911,12913,12915],{"class":72,"line":12910},150,[70,12912,8296],{"class":264},[70,12914,8645],{"class":76},[70,12916,2240],{"class":264},[70,12918,12920],{"class":72,"line":12919},151,[70,12921,252],{"emptyLinePlaceholder":251},[70,12923,12925],{"class":72,"line":12924},152,[70,12926,12927],{"class":295},"        \u002F\u002F 如果队列还有数据，继续发送新的队首。\n",[70,12929,12931,12933,12935,12937,12939,12941],{"class":72,"line":12930},153,[70,12932,7929],{"class":219},[70,12934,8350],{"class":264},[70,12936,8353],{"class":219},[70,12938,8272],{"class":264},[70,12940,8275],{"class":76},[70,12942,8674],{"class":264},[70,12944,12946],{"class":72,"line":12945},154,[70,12947,7936],{"class":264},[70,12949,12951,12953],{"class":72,"line":12950},155,[70,12952,8365],{"class":76},[70,12954,2240],{"class":264},[70,12956,12958],{"class":72,"line":12957},156,[70,12959,7978],{"class":264},[70,12961,12963],{"class":72,"line":12962},157,[70,12964,366],{"class":264},[70,12966,12968],{"class":72,"line":12967},158,[70,12969,252],{"emptyLinePlaceholder":251},[70,12971,12973],{"class":72,"line":12972},159,[70,12974,8384],{"class":219},[70,12976,12978,12980,12982,12984],{"class":72,"line":12977},160,[70,12979,383],{"class":76},[70,12981,386],{"class":264},[70,12983,389],{"class":76},[70,12985,8718],{"class":264},[70,12987,12989],{"class":72,"line":12988},161,[70,12990,252],{"emptyLinePlaceholder":251},[70,12992,12994],{"class":72,"line":12993},162,[70,12995,10532],{"class":295},[70,12997,12999,13001,13003,13005,13007,13009,13011],{"class":72,"line":12998},163,[70,13000,302],{"class":76},[70,13002,1623],{"class":264},[70,13004,1626],{"class":219},[70,13006,274],{"class":264},[70,13008,1631],{"class":124},[70,13010,1634],{"class":219},[70,13012,13013],{"class":264}," read_buffer_{};\n",[70,13015,13017],{"class":72,"line":13016},164,[70,13018,252],{"emptyLinePlaceholder":251},[70,13020,13022],{"class":72,"line":13021},165,[70,13023,13024],{"class":295},"    \u002F\u002F 保存正在发送以及等待发送的数据。\n",[70,13026,13028,13030,13032,13034,13036,13038,13040],{"class":72,"line":13027},166,[70,13029,302],{"class":76},[70,13031,8737],{"class":264},[70,13033,6226],{"class":219},[70,13035,2058],{"class":76},[70,13037,8744],{"class":264},[70,13039,1634],{"class":219},[70,13041,8749],{"class":264},[70,13043,13045],{"class":72,"line":13044},167,[70,13046,8755],{"class":264},[70,13048,13050],{"class":72,"line":13049},168,[70,13051,252],{"emptyLinePlaceholder":251},[70,13053,13055,13057,13059,13061,13063,13065,13067,13069,13071],{"class":72,"line":13054},169,[70,13056,258],{"class":219},[70,13058,261],{"class":76},[70,13060,265],{"class":264},[70,13062,258],{"class":219},[70,13064,271],{"class":270},[70,13066,274],{"class":264},[70,13068,277],{"class":219},[70,13070,280],{"class":270},[70,13072,283],{"class":264},[70,13074,13076],{"class":72,"line":13075},170,[70,13077,289],{"class":264},[70,13079,13081,13083,13085,13087,13089],{"class":72,"line":13080},171,[70,13082,302],{"class":76},[70,13084,305],{"class":264},[70,13086,308],{"class":219},[70,13088,311],{"class":80},[70,13090,314],{"class":264},[70,13092,13094],{"class":72,"line":13093},172,[70,13095,252],{"emptyLinePlaceholder":251},[70,13097,13099,13101,13103,13105,13107],{"class":72,"line":13098},173,[70,13100,325],{"class":219},[70,13102,328],{"class":264},[70,13104,331],{"class":219},[70,13106,334],{"class":124},[70,13108,337],{"class":264},[70,13110,13112],{"class":72,"line":13111},174,[70,13113,343],{"class":264},[70,13115,13117,13119,13121,13123,13125],{"class":72,"line":13116},175,[70,13118,349],{"class":264},[70,13120,308],{"class":219},[70,13122,354],{"class":264},[70,13124,357],{"class":124},[70,13126,360],{"class":264},[70,13128,13130],{"class":72,"line":13129},176,[70,13131,366],{"class":264},[70,13133,13135],{"class":72,"line":13134},177,[70,13136,252],{"emptyLinePlaceholder":251},[70,13138,13140,13142,13144,13146],{"class":72,"line":13139},178,[70,13141,383],{"class":76},[70,13143,386],{"class":264},[70,13145,389],{"class":76},[70,13147,392],{"class":264},[70,13149,13151],{"class":72,"line":13150},179,[70,13152,252],{"emptyLinePlaceholder":251},[70,13154,13156,13159,13161],{"class":72,"line":13155},180,[70,13157,13158],{"class":264},"    AsyncSerialPort ",[70,13160,413],{"class":76},[70,13162,8873],{"class":264},[70,13164,13166],{"class":72,"line":13165},181,[70,13167,252],{"emptyLinePlaceholder":251},[70,13169,13171],{"class":72,"line":13170},182,[70,13172,13173],{"class":295},"    \u002F\u002F 先注册几条异步发送任务。\n",[70,13175,13177,13179,13181,13183,13185,13187,13189],{"class":72,"line":13176},183,[70,13178,463],{"class":264},[70,13180,7685],{"class":76},[70,13182,265],{"class":264},[70,13184,7690],{"class":80},[70,13186,753],{"class":124},[70,13188,756],{"class":80},[70,13190,898],{"class":264},[70,13192,13194,13196,13198,13200,13202,13204,13206],{"class":72,"line":13193},184,[70,13195,463],{"class":264},[70,13197,7685],{"class":76},[70,13199,265],{"class":264},[70,13201,7705],{"class":80},[70,13203,753],{"class":124},[70,13205,756],{"class":80},[70,13207,898],{"class":264},[70,13209,13211,13213,13215,13217,13219,13221,13223],{"class":72,"line":13210},185,[70,13212,463],{"class":264},[70,13214,7685],{"class":76},[70,13216,265],{"class":264},[70,13218,7720],{"class":80},[70,13220,753],{"class":124},[70,13222,756],{"class":80},[70,13224,898],{"class":264},[70,13226,13228],{"class":72,"line":13227},186,[70,13229,252],{"emptyLinePlaceholder":251},[70,13231,13233,13235,13237,13239],{"class":72,"line":13232},187,[70,13234,302],{"class":76},[70,13236,386],{"class":264},[70,13238,444],{"class":76},[70,13240,620],{"class":264},[70,13242,13244,13247],{"class":72,"line":13243},188,[70,13245,13246],{"class":80},"        \"main：开始 io.run()，按 Ctrl+C 结束程序\"",[70,13248,898],{"class":264},[70,13250,13252],{"class":72,"line":13251},189,[70,13253,252],{"emptyLinePlaceholder":251},[70,13255,13257,13259,13261],{"class":72,"line":13256},190,[70,13258,5224],{"class":264},[70,13260,2237],{"class":76},[70,13262,2240],{"class":264},[70,13264,13266],{"class":72,"line":13265},191,[70,13267,252],{"emptyLinePlaceholder":251},[70,13269,13271,13273,13275,13277,13279,13281],{"class":72,"line":13270},192,[70,13272,302],{"class":76},[70,13274,386],{"class":264},[70,13276,444],{"class":76},[70,13278,265],{"class":264},[70,13280,5247],{"class":80},[70,13282,898],{"class":264},[70,13284,13286],{"class":72,"line":13285},193,[70,13287,252],{"emptyLinePlaceholder":251},[70,13289,13291,13293,13295],{"class":72,"line":13290},194,[70,13292,909],{"class":219},[70,13294,912],{"class":124},[70,13296,314],{"class":264},[70,13298,13300],{"class":72,"line":13299},195,[70,13301,920],{"class":264},[55,13303,930],{"id":13304},"编译运行-6",[15,13306,933],{},[22,13308,13309],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,13310,13311,13321,13327],{"__ignoreMap":28},[70,13312,13313,13315,13317,13319],{"class":72,"line":73},[70,13314,52],{"class":76},[70,13316,125],{"class":124},[70,13318,125],{"class":124},[70,13320,130],{"class":124},[70,13322,13323,13325],{"class":72,"line":133},[70,13324,136],{"class":80},[70,13326,130],{"class":124},[70,13328,13329],{"class":72,"line":141},[70,13330,144],{"class":80},[15,13332,1929],{},[22,13334,13336],{"className":13335,"code":1933,"language":27,"meta":28},[25],[30,13337,1933],{"__ignoreMap":28},[15,13339,13340],{},"终端 2：监听程序发送的数据。",[22,13342,13343],{"className":64,"code":963,"language":66,"meta":28,"style":28},[30,13344,13345],{"__ignoreMap":28},[70,13346,13347,13349],{"class":72,"line":73},[70,13348,970],{"class":76},[70,13350,973],{"class":80},[15,13352,13353],{},"编译运行程序。",[15,13355,13356,13357,13359],{},"如果还要测试接收，可以再开一个终端向 ",[30,13358,172],{}," 写入：",[22,13361,13363],{"className":64,"code":13362,"language":66,"meta":28,"style":28},"printf 'hello asio\\n' > \u002Fdev\u002Fpts\u002F4\n",[30,13364,13365],{"__ignoreMap":28},[70,13366,13367,13369,13371,13373],{"class":72,"line":73},[70,13368,10778],{"class":124},[70,13370,10781],{"class":80},[70,13372,1976],{"class":219},[70,13374,973],{"class":80},[15,13376,2048],{},[22,13378,13380],{"className":13379,"code":1136,"language":27,"meta":28},[25],[30,13381,1136],{"__ignoreMap":28},[15,13383,13384],{},"正好是 11 字节。",[15,13386,13387],{},[995,13388],{"alt":28,"src":13389},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789474872653-4ef0ae31.webp",[15,13391,13392],{},[995,13393],{"alt":28,"src":13394},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789474887133-7cae0874.webp",[55,13396,13397],{"id":13397},"整个类的工作过程",[15,13399,13400],{},"程序创建：",[22,13402,13404],{"className":210,"code":13403,"language":212,"meta":28,"style":28},"AsyncSerialPort serial(io, port_name);\n",[30,13405,13406],{"__ignoreMap":28},[70,13407,13408,13410,13412,13414,13416,13418,13420],{"class":72,"line":73},[70,13409,12464],{"class":76},[70,13411,5853],{"class":76},[70,13413,265],{"class":264},[70,13415,10907],{"class":76},[70,13417,274],{"class":264},[70,13419,10912],{"class":76},[70,13421,898],{"class":264},[15,13423,13424],{},"构造函数最后调用：",[22,13426,13427],{"className":210,"code":9746,"language":212,"meta":28,"style":28},[30,13428,13429],{"__ignoreMap":28},[70,13430,13431,13433],{"class":72,"line":73},[70,13432,9753],{"class":76},[70,13434,2240],{"class":264},[15,13436,13437],{},"因此首先注册一个：",[22,13439,13442],{"className":13440,"code":13441,"language":27,"meta":28},[25],"异步接收 11 字节\n",[30,13443,13441],{"__ignoreMap":28},[15,13445,6104],{},[15,13447,13448],{},"与此同时：",[22,13450,13452],{"className":210,"code":13451,"language":212,"meta":28,"style":28},"serial.async_send(\"message one\\n\");\nserial.async_send(\"message two\\n\");\nserial.async_send(\"message three\\n\");\n",[30,13453,13454,13470,13486],{"__ignoreMap":28},[70,13455,13456,13458,13460,13462,13464,13466,13468],{"class":72,"line":73},[70,13457,3970],{"class":264},[70,13459,7685],{"class":76},[70,13461,265],{"class":264},[70,13463,7690],{"class":80},[70,13465,753],{"class":124},[70,13467,756],{"class":80},[70,13469,898],{"class":264},[70,13471,13472,13474,13476,13478,13480,13482,13484],{"class":72,"line":133},[70,13473,3970],{"class":264},[70,13475,7685],{"class":76},[70,13477,265],{"class":264},[70,13479,7705],{"class":80},[70,13481,753],{"class":124},[70,13483,756],{"class":80},[70,13485,898],{"class":264},[70,13487,13488,13490,13492,13494,13496,13498,13500],{"class":72,"line":141},[70,13489,3970],{"class":264},[70,13491,7685],{"class":76},[70,13493,265],{"class":264},[70,13495,7720],{"class":80},[70,13497,753],{"class":124},[70,13499,756],{"class":80},[70,13501,898],{"class":264},[15,13503,13504],{},"又建立了发送队列：",[22,13506,13509],{"className":13507,"code":13508,"language":27,"meta":28},[25],"message one   ← 正在发送\nmessage two   ← 等待\nmessage three ← 等待\n",[30,13510,13508],{"__ignoreMap":28},[15,13512,3182],{},[22,13514,13517],{"className":13515,"code":13516,"language":27,"meta":28},[25],"                     AsyncSerialPort\n                           │\n             ┌─────────────┴─────────────┐\n             ↓                           ↓\n           接收                         发送\n             ↓                           ↓\n      async_read()                async_write()\n             ↓                           ↓\n        on_read()                   on_write()\n             ↓                           ↓\n      再次 async_read()          发送下一条\n",[30,13518,13516],{"__ignoreMap":28},[15,13520,13521],{},"接收和发送可以同时存在。",[15,13523,13524],{},"也就是说：",[22,13526,13529],{"className":13527,"code":13528,"language":27,"meta":28},[25],"一个异步读操作\n+\n一个异步写操作\n",[30,13530,13528],{"__ignoreMap":28},[15,13532,13533],{},"可以同时挂在同一个串口对象上。",[40,13535],{},[55,13537,13539,13540,11288],{"id":13538},"为什么这里不需要-mutex","为什么这里不需要 ",[30,13541,13542],{},"mutex",[15,13544,13545],{},"虽然：",[22,13547,13549],{"className":210,"code":13548,"language":212,"meta":28,"style":28},"read_buffer_\nwrite_queue_\n",[30,13550,13551,13556],{"__ignoreMap":28},[70,13552,13553],{"class":72,"line":73},[70,13554,13555],{"class":264},"read_buffer_\n",[70,13557,13558],{"class":72,"line":133},[70,13559,13560],{"class":264},"write_queue_\n",[15,13562,13563],{},"都是成员变量，但是本示例只有：",[22,13565,13567],{"className":210,"code":13566,"language":212,"meta":28,"style":28},"main 线程\n",[30,13568,13569],{"__ignoreMap":28},[70,13570,13571],{"class":72,"line":73},[70,13572,13566],{"class":264},[15,13574,13575],{},"调用：",[22,13577,13578],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,13579,13580],{"__ignoreMap":28},[70,13581,13582,13584,13586],{"class":72,"line":73},[70,13583,2234],{"class":264},[70,13585,2237],{"class":76},[70,13587,2240],{"class":264},[15,13589,13590],{},"所以所有异步 handler：",[22,13592,13595],{"className":13593,"code":13594,"language":27,"meta":28},[25],"on_read()\non_write()\n",[30,13596,13594],{"__ignoreMap":28},[15,13598,13599],{},"实际上都在同一个线程中一个接一个执行。",[15,13601,13602],{},"不会出现：",[22,13604,13607],{"className":13605,"code":13606,"language":27,"meta":28},[25],"线程 1：on_read()\n\n同时\n\n线程 2：on_write()\n",[30,13608,13606],{"__ignoreMap":28},[15,13610,13611],{},"因此这里暂时没有多个线程同时访问：",[22,13613,13615],{"className":210,"code":13614,"language":212,"meta":28,"style":28},"write_queue_\nread_buffer_\n",[30,13616,13617,13621],{"__ignoreMap":28},[70,13618,13619],{"class":72,"line":73},[70,13620,13560],{"class":264},[70,13622,13623],{"class":72,"line":133},[70,13624,13555],{"class":264},[15,13626,13627],{},"的问题。",[15,13629,13630],{},"所以不需要：",[22,13632,13634],{"className":210,"code":13633,"language":212,"meta":28,"style":28},"std::mutex\n",[30,13635,13636],{"__ignoreMap":28},[70,13637,13638,13640],{"class":72,"line":73},[70,13639,2058],{"class":76},[70,13641,13642],{"class":264},"::mutex\n",[15,13644,13645],{},"也不需要：",[22,13647,13649],{"className":210,"code":13648,"language":212,"meta":28,"style":28},"strand\n",[30,13650,13651],{"__ignoreMap":28},[70,13652,13653],{"class":72,"line":73},[70,13654,13648],{"class":264},[40,13656],{},[55,13658,13659],{"id":13659},"本示例最重要的结构",[15,13661,13662],{},"可以把整个类记成：",[22,13664,13667],{"className":13665,"code":13666,"language":27,"meta":28},[25],"接收：\n\nstart_read()\n↓\nasync_read()\n↓\non_read()\n↓\n处理数据\n↓\nstart_read()\n",[30,13668,13666],{"__ignoreMap":28},[15,13670,13671],{},"发送：",[22,13673,13676],{"className":13674,"code":13675,"language":27,"meta":28},[25],"async_send()\n↓\n加入 write_queue_\n↓\ndo_write()\n↓\nasync_write()\n↓\non_write()\n↓\npop_front()\n↓\n继续下一条\n",[30,13677,13675],{"__ignoreMap":28},[15,13679,3227],{},[12,13681,13682],{},[15,13683,13684],{},"一个完整的异步串口类，通常同时包含“持续读取链”和“发送队列链”。",[40,13686],{},[43,13688,13690],{"id":13689},"示例-8主线程产生数据独立-asio-线程负责串口通信","示例 8：主线程产生数据，独立 Asio 线程负责串口通信",[15,13692,13693],{},"这种情况一般适用于一个串口设备。（此时main有1个主线程，asio有1个线程）",[55,13695,186],{"id":13696},"程序目标-7",[15,13698,13699],{},"示例 7 中：",[22,13701,13702],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,13703,13704],{"__ignoreMap":28},[70,13705,13706,13708,13710],{"class":72,"line":73},[70,13707,2234],{"class":264},[70,13709,2237],{"class":76},[70,13711,2240],{"class":264},[15,13713,13714],{},"直接运行在 main 线程。",[15,13716,13717],{},"这意味着：",[22,13719,13722],{"className":13720,"code":13721,"language":27,"meta":28},[25],"main 线程\n↓\n进入 io.run()\n↓\n长期负责 Asio 事件循环\n",[30,13723,13721],{"__ignoreMap":28},[15,13725,13726],{},"实际程序中，经常希望：",[22,13728,13731],{"className":13729,"code":13730,"language":27,"meta":28},[25],"main 线程\n→ 继续处理自己的业务逻辑\n\nAsio 线程\n→ 专门处理串口收发\n",[30,13732,13730],{"__ignoreMap":28},[15,13734,13735],{},"于是程序变成：",[22,13737,13740],{"className":13738,"code":13739,"language":27,"meta":28},[25],"                 主线程\n                   │\n          产生需要发送的数据\n                   │\n                   ↓\n        serial.async_send(...)\n                   │\n                   ↓\n                post()\n                   │\n                   ↓\n================================\n              Asio 线程\n================================\n                   │\n                   ↓\n             write_queue_\n                   │\n                   ↓\n             async_write()\n                   │\n                   ↓\n                 串口\n",[30,13741,13739],{"__ignoreMap":28},[15,13743,13744],{},"与此同时串口接收也是：",[22,13746,13749],{"className":13747,"code":13748,"language":27,"meta":28},[25],"串口\n ↓\nasync_read()\n ↓\nAsio 线程执行 on_read()\n",[30,13750,13748],{"__ignoreMap":28},[15,13752,13753],{},"这样：",[12,13755,13756],{},[15,13757,13758],{},"main 线程负责“产生任务”，Asio 线程负责“真正处理串口”。",[55,13760,207],{"id":13761},"完整代码-7",[22,13763,13765],{"className":210,"code":13764,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Carray>\n#include \u003Cdeque>\n#include \u003Cfunctional>\n#include \u003Ciostream>\n#include \u003Cprint>\n#include \u003Cstring>\n#include \u003Cthread>\n\nclass AsyncSerialPort\n{\npublic:\n    AsyncSerialPort(\n        boost::asio::io_context& io,\n        const std::string& port_name)\n        : io_(io),\n          serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n\n        if (ec)\n        {\n            std::println(\n                \"打开串口失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        serial_.set_option(\n            boost::asio::serial_port_base::baud_rate(115200));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::character_size(8));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::parity(\n                boost::asio::serial_port_base::parity::none));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::stop_bits(\n                boost::asio::serial_port_base::stop_bits::one));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::flow_control(\n                boost::asio::serial_port_base::flow_control::none));\n\n        std::println(\n            \"AsyncSerialPort：串口打开成功\");\n    }\n\n    void start()\n    {\n        \u002F\u002F 不直接在调用 start() 的线程里操作内部状态，\n        \u002F\u002F 而是把 start_read() 投递给 io_context。\n        boost::asio::post(\n            io_,\n            std::bind(\n                &AsyncSerialPort::start_read,\n                this));\n    }\n\n    void async_send(const std::string& msg)\n    {\n        \u002F\u002F main 线程不直接修改 write_queue_。\n        \u002F\u002F 只把“加入发送队列”这个任务投递给 Asio 线程。\n        boost::asio::post(\n            io_,\n            std::bind(\n                &AsyncSerialPort::enqueue_write,\n                this,\n                msg));\n    }\n\n    void stop()\n    {\n        \u002F\u002F 停止操作也交给 Asio 线程完成。\n        boost::asio::post(\n            io_,\n            std::bind(\n                &AsyncSerialPort::do_stop,\n                this));\n    }\n\nprivate:\n    void start_read()\n    {\n        if (stopping_ || !serial_.is_open())\n        {\n            return;\n        }\n\n        std::println(\n            \"Asio线程：等待下一组 11 字节\");\n\n        boost::asio::async_read(\n            serial_,\n            boost::asio::buffer(read_buffer_),\n            std::bind(\n                &AsyncSerialPort::on_read,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_read(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"读取结束：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::string msg(\n            read_buffer_.data(),\n            bytes_transferred);\n\n        std::println(\n            \"Asio线程：收到数据，字节数 = {}，内容 = {}\",\n            bytes_transferred,\n            msg);\n\n        if (!stopping_)\n        {\n            start_read();\n        }\n    }\n\n    void enqueue_write(std::string msg)\n    {\n        if (stopping_)\n        {\n            return;\n        }\n\n        bool writing = !write_queue_.empty();\n\n        write_queue_.push_back(msg);\n\n        std::print(\n            \"Asio线程：加入发送队列：{}\",\n            msg);\n\n        if (!writing)\n        {\n            do_write();\n        }\n    }\n\n    void do_write()\n    {\n        if (stopping_ || write_queue_.empty())\n        {\n            return;\n        }\n\n        boost::asio::async_write(\n            serial_,\n            boost::asio::buffer(\n                write_queue_.front()),\n            std::bind(\n                &AsyncSerialPort::on_write,\n                this,\n                std::placeholders::_1,\n                std::placeholders::_2));\n    }\n\n    void on_write(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"发送结束：{}\",\n                ec.message());\n\n            return;\n        }\n\n        std::println(\n            \"Asio线程：发送完成，字节数 = {}\",\n            bytes_transferred);\n\n        write_queue_.pop_front();\n\n        if (!write_queue_.empty())\n        {\n            do_write();\n        }\n    }\n\n    void do_stop()\n    {\n        if (stopping_)\n        {\n            return;\n        }\n\n        stopping_ = true;\n\n        std::println(\n            \"Asio线程：开始关闭串口\");\n\n        boost::system::error_code ec;\n\n        serial_.cancel(ec);\n\n        ec.clear();\n\n        serial_.close(ec);\n    }\n\nprivate:\n    boost::asio::io_context& io_;\n\n    boost::asio::serial_port serial_;\n\n    std::array\u003Cchar, 11> read_buffer_{};\n\n    std::deque\u003Cstd::string> write_queue_;\n\n    bool stopping_ = false;\n};\n\nvoid run_io(boost::asio::io_context* io)\n{\n    std::println(\n        \"Asio线程：开始 io.run()，线程 id = {}\",\n        std::this_thread::get_id());\n\n    io->run();\n\n    std::println(\n        \"Asio线程：io.run() 返回\");\n}\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    \u002F\u002F 保证 Asio 后台线程即使暂时没有任务，\n    \u002F\u002F io.run() 也不会立刻返回。\n    auto guard =\n        boost::asio::make_work_guard(io);\n\n    AsyncSerialPort serial(io, port_name);\n\n    \u002F\u002F 单独创建一个线程运行 Asio 事件循环。\n    std::thread io_thread(\n        std::bind(\n            run_io,\n            &io));\n\n    \u002F\u002F 此时 Asio 线程已经可能进入 io.run()。\n    \u002F\u002F start() 把第一次读取任务投递给 Asio 线程。\n    serial.start();\n\n    std::println(\n        \"main线程 id = {}\",\n        std::this_thread::get_id());\n\n    \u002F\u002F 模拟 main 中的其他业务逻辑不断产生待发送数据。\n    serial.async_send(\"message one\\n\");\n    serial.async_send(\"message two\\n\");\n    serial.async_send(\"message three\\n\");\n\n    std::println(\n        \"main：数据已经提交给 Asio，main 可以继续处理其他工作\");\n\n    std::println(\n        \"main：按 Enter 结束程序\");\n\n    std::string input;\n    std::getline(std::cin, input);\n\n    \u002F\u002F 把关闭串口任务投递给 Asio 线程。\n    serial.stop();\n\n    \u002F\u002F 允许 io.run() 在剩余任务处理完成后自然返回。\n    guard.reset();\n\n    io_thread.join();\n\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n",[30,13766,13767,13773,13779,13785,13791,13797,13804,13810,13816,13823,13827,13833,13837,13841,13847,13865,13881,13891,13898,13902,13912,13916,13924,13928,13934,13938,13948,13954,13962,13966,13972,13976,13980,13988,14010,14014,14022,14044,14048,14056,14074,14092,14096,14104,14122,14140,14144,14152,14170,14188,14192,14202,14208,14212,14216,14225,14229,14234,14239,14254,14259,14269,14278,14284,14288,14292,14314,14318,14323,14328,14342,14346,14356,14365,14371,14376,14380,14384,14393,14397,14402,14416,14420,14430,14439,14445,14449,14453,14457,14465,14469,14489,14493,14499,14503,14507,14517,14524,14528,14542,14546,14560,14570,14578,14584,14594,14604,14608,14612,14620,14640,14652,14656,14662,14666,14676,14683,14691,14695,14701,14705,14709,14719,14727,14731,14735,14745,14752,14756,14760,14764,14775,14779,14786,14790,14794,14798,14817,14821,14828,14832,14838,14842,14846,14862,14866,14874,14878,14888,14895,14899,14903,14913,14917,14923,14927,14931,14935,14943,14947,14962,14966,14972,14976,14980,14994,14998,15012,15020,15030,15038,15044,15054,15064,15068,15072,15080,15100,15112,15116,15122,15126,15136,15143,15151,15155,15161,15165,15169,15179,15186,15190,15194,15202,15206,15220,15225,15232,15237,15242,15247,15257,15262,15269,15274,15281,15286,15291,15304,15309,15320,15328,15333,15344,15349,15360,15365,15376,15381,15391,15396,15401,15406,15423,15428,15439,15444,15461,15466,15483,15488,15504,15509,15514,15540,15545,15556,15564,15581,15586,15596,15601,15612,15620,15625,15630,15651,15656,15669,15674,15687,15692,15705,15710,15715,15726,15731,15737,15743,15754,15770,15775,15784,15789,15795,15808,15819,15825,15833,15838,15844,15850,15860,15865,15876,15884,15899,15904,15910,15927,15944,15961,15966,15977,15985,15990,16001,16009,16014,16022,16039,16044,16050,16060,16065,16071,16082,16087,16098,16103,16118,16123,16132],{"__ignoreMap":28},[70,13768,13769,13771],{"class":72,"line":73},[70,13770,220],{"class":219},[70,13772,223],{"class":80},[70,13774,13775,13777],{"class":72,"line":133},[70,13776,220],{"class":219},[70,13778,230],{"class":80},[70,13780,13781,13783],{"class":72,"line":141},[70,13782,220],{"class":219},[70,13784,1172],{"class":80},[70,13786,13787,13789],{"class":72,"line":240},[70,13788,220],{"class":219},[70,13790,7797],{"class":80},[70,13792,13793,13795],{"class":72,"line":248},[70,13794,220],{"class":219},[70,13796,4504],{"class":80},[70,13798,13799,13801],{"class":72,"line":255},[70,13800,220],{"class":219},[70,13802,13803],{"class":80}," \u003Ciostream>\n",[70,13805,13806,13808],{"class":72,"line":286},[70,13807,220],{"class":219},[70,13809,237],{"class":80},[70,13811,13812,13814],{"class":72,"line":292},[70,13813,220],{"class":219},[70,13815,245],{"class":80},[70,13817,13818,13820],{"class":72,"line":299},[70,13819,220],{"class":219},[70,13821,13822],{"class":80}," \u003Cthread>\n",[70,13824,13825],{"class":72,"line":317},[70,13826,252],{"emptyLinePlaceholder":251},[70,13828,13829,13831],{"class":72,"line":322},[70,13830,7824],{"class":219},[70,13832,11847],{"class":76},[70,13834,13835],{"class":72,"line":340},[70,13836,289],{"class":264},[70,13838,13839],{"class":72,"line":346},[70,13840,7836],{"class":219},[70,13842,13843,13845],{"class":72,"line":363},[70,13844,11860],{"class":76},[70,13846,620],{"class":264},[70,13848,13849,13851,13853,13855,13857,13859,13861,13863],{"class":72,"line":369},[70,13850,626],{"class":76},[70,13852,386],{"class":264},[70,13854,389],{"class":76},[70,13856,386],{"class":264},[70,13858,7856],{"class":76},[70,13860,4549],{"class":219},[70,13862,7861],{"class":270},[70,13864,4555],{"class":264},[70,13866,13867,13869,13871,13873,13875,13877,13879],{"class":72,"line":374},[70,13868,7868],{"class":219},[70,13870,7871],{"class":76},[70,13872,386],{"class":264},[70,13874,3196],{"class":76},[70,13876,4549],{"class":219},[70,13878,7880],{"class":270},[70,13880,337],{"class":264},[70,13882,13883,13885,13888],{"class":72,"line":380},[70,13884,7887],{"class":264},[70,13886,13887],{"class":76},"io_",[70,13889,13890],{"class":264},"(io),\n",[70,13892,13893,13896],{"class":72,"line":395},[70,13894,13895],{"class":76},"          serial_",[70,13897,7893],{"class":264},[70,13899,13900],{"class":72,"line":401},[70,13901,343],{"class":264},[70,13903,13904,13906,13908,13910],{"class":72,"line":419},[70,13905,626],{"class":76},[70,13907,386],{"class":264},[70,13909,426],{"class":76},[70,13911,429],{"class":264},[70,13913,13914],{"class":72,"line":432},[70,13915,252],{"emptyLinePlaceholder":251},[70,13917,13918,13920,13922],{"class":72,"line":437},[70,13919,7916],{"class":264},[70,13921,466],{"class":76},[70,13923,469],{"class":264},[70,13925,13926],{"class":72,"line":455},[70,13927,252],{"emptyLinePlaceholder":251},[70,13929,13930,13932],{"class":72,"line":460},[70,13931,7929],{"class":219},[70,13933,477],{"class":264},[70,13935,13936],{"class":72,"line":472},[70,13937,7936],{"class":264},[70,13939,13940,13942,13944,13946],{"class":72,"line":480},[70,13941,5156],{"class":76},[70,13943,386],{"class":264},[70,13945,444],{"class":76},[70,13947,620],{"class":264},[70,13949,13950,13952],{"class":72,"line":485},[70,13951,7951],{"class":80},[70,13953,4555],{"class":264},[70,13955,13956,13958,13960],{"class":72,"line":509},[70,13957,7958],{"class":264},[70,13959,503],{"class":76},[70,13961,506],{"class":264},[70,13963,13964],{"class":72,"line":520},[70,13965,252],{"emptyLinePlaceholder":251},[70,13967,13968,13970],{"class":72,"line":525},[70,13969,7971],{"class":219},[70,13971,314],{"class":264},[70,13973,13974],{"class":72,"line":530},[70,13975,7978],{"class":264},[70,13977,13978],{"class":72,"line":565},[70,13979,252],{"emptyLinePlaceholder":251},[70,13981,13982,13984,13986],{"class":72,"line":596},[70,13983,7916],{"class":264},[70,13985,535],{"class":76},[70,13987,620],{"class":264},[70,13989,13990,13992,13994,13996,13998,14000,14002,14004,14006,14008],{"class":72,"line":623},[70,13991,1496],{"class":76},[70,13993,386],{"class":264},[70,13995,389],{"class":76},[70,13997,386],{"class":264},[70,13999,549],{"class":76},[70,14001,386],{"class":264},[70,14003,554],{"class":76},[70,14005,265],{"class":264},[70,14007,559],{"class":124},[70,14009,562],{"class":264},[70,14011,14012],{"class":72,"line":644},[70,14013,252],{"emptyLinePlaceholder":251},[70,14015,14016,14018,14020],{"class":72,"line":670},[70,14017,7916],{"class":264},[70,14019,535],{"class":76},[70,14021,620],{"class":264},[70,14023,14024,14026,14028,14030,14032,14034,14036,14038,14040,14042],{"class":72,"line":690},[70,14025,1496],{"class":76},[70,14027,386],{"class":264},[70,14029,389],{"class":76},[70,14031,386],{"class":264},[70,14033,549],{"class":76},[70,14035,386],{"class":264},[70,14037,586],{"class":76},[70,14039,265],{"class":264},[70,14041,591],{"class":124},[70,14043,562],{"class":264},[70,14045,14046],{"class":72,"line":716},[70,14047,252],{"emptyLinePlaceholder":251},[70,14049,14050,14052,14054],{"class":72,"line":735},[70,14051,7916],{"class":264},[70,14053,535],{"class":76},[70,14055,620],{"class":264},[70,14057,14058,14060,14062,14064,14066,14068,14070,14072],{"class":72,"line":740},[70,14059,1496],{"class":76},[70,14061,386],{"class":264},[70,14063,389],{"class":76},[70,14065,386],{"class":264},[70,14067,549],{"class":76},[70,14069,386],{"class":264},[70,14071,617],{"class":76},[70,14073,620],{"class":264},[70,14075,14076,14078,14080,14082,14084,14086,14088,14090],{"class":72,"line":761},[70,14077,8081],{"class":76},[70,14079,386],{"class":264},[70,14081,389],{"class":76},[70,14083,386],{"class":264},[70,14085,549],{"class":76},[70,14087,386],{"class":264},[70,14089,617],{"class":76},[70,14091,641],{"class":264},[70,14093,14094],{"class":72,"line":766},[70,14095,252],{"emptyLinePlaceholder":251},[70,14097,14098,14100,14102],{"class":72,"line":772},[70,14099,7916],{"class":264},[70,14101,535],{"class":76},[70,14103,620],{"class":264},[70,14105,14106,14108,14110,14112,14114,14116,14118,14120],{"class":72,"line":816},[70,14107,1496],{"class":76},[70,14109,386],{"class":264},[70,14111,389],{"class":76},[70,14113,386],{"class":264},[70,14115,549],{"class":76},[70,14117,386],{"class":264},[70,14119,665],{"class":76},[70,14121,620],{"class":264},[70,14123,14124,14126,14128,14130,14132,14134,14136,14138],{"class":72,"line":823},[70,14125,8081],{"class":76},[70,14127,386],{"class":264},[70,14129,389],{"class":76},[70,14131,386],{"class":264},[70,14133,549],{"class":76},[70,14135,386],{"class":264},[70,14137,665],{"class":76},[70,14139,687],{"class":264},[70,14141,14142],{"class":72,"line":828},[70,14143,252],{"emptyLinePlaceholder":251},[70,14145,14146,14148,14150],{"class":72,"line":848},[70,14147,7916],{"class":264},[70,14149,535],{"class":76},[70,14151,620],{"class":264},[70,14153,14154,14156,14158,14160,14162,14164,14166,14168],{"class":72,"line":857},[70,14155,1496],{"class":76},[70,14157,386],{"class":264},[70,14159,389],{"class":76},[70,14161,386],{"class":264},[70,14163,549],{"class":76},[70,14165,386],{"class":264},[70,14167,711],{"class":76},[70,14169,620],{"class":264},[70,14171,14172,14174,14176,14178,14180,14182,14184,14186],{"class":72,"line":862},[70,14173,8081],{"class":76},[70,14175,386],{"class":264},[70,14177,389],{"class":76},[70,14179,386],{"class":264},[70,14181,549],{"class":76},[70,14183,386],{"class":264},[70,14185,711],{"class":76},[70,14187,641],{"class":264},[70,14189,14190],{"class":72,"line":867},[70,14191,252],{"emptyLinePlaceholder":251},[70,14193,14194,14196,14198,14200],{"class":72,"line":884},[70,14195,488],{"class":76},[70,14197,386],{"class":264},[70,14199,444],{"class":76},[70,14201,620],{"class":264},[70,14203,14204,14206],{"class":72,"line":901},[70,14205,12213],{"class":80},[70,14207,898],{"class":264},[70,14209,14210],{"class":72,"line":906},[70,14211,366],{"class":264},[70,14213,14214],{"class":72,"line":917},[70,14215,252],{"emptyLinePlaceholder":251},[70,14217,14218,14220,14223],{"class":72,"line":1618},[70,14219,8223],{"class":219},[70,14221,14222],{"class":76}," start",[70,14224,3162],{"class":264},[70,14226,14227],{"class":72,"line":1640},[70,14228,343],{"class":264},[70,14230,14231],{"class":72,"line":1645},[70,14232,14233],{"class":295},"        \u002F\u002F 不直接在调用 start() 的线程里操作内部状态，\n",[70,14235,14236],{"class":72,"line":1661},[70,14237,14238],{"class":295},"        \u002F\u002F 而是把 start_read() 投递给 io_context。\n",[70,14240,14241,14243,14245,14247,14249,14252],{"class":72,"line":1666},[70,14242,626],{"class":76},[70,14244,386],{"class":264},[70,14246,389],{"class":76},[70,14248,386],{"class":264},[70,14250,14251],{"class":76},"post",[70,14253,620],{"class":264},[70,14255,14256],{"class":72,"line":1672},[70,14257,14258],{"class":264},"            io_,\n",[70,14260,14261,14263,14265,14267],{"class":72,"line":1678},[70,14262,5156],{"class":76},[70,14264,386],{"class":264},[70,14266,5144],{"class":76},[70,14268,620],{"class":264},[70,14270,14271,14273,14275],{"class":72,"line":1692},[70,14272,8461],{"class":219},[70,14274,12464],{"class":76},[70,14276,14277],{"class":264},"::start_read,\n",[70,14279,14280,14282],{"class":72,"line":1708},[70,14281,8472],{"class":124},[70,14283,562],{"class":264},[70,14285,14286],{"class":72,"line":1714},[70,14287,366],{"class":264},[70,14289,14290],{"class":72,"line":1730},[70,14291,252],{"emptyLinePlaceholder":251},[70,14293,14294,14296,14298,14300,14302,14304,14306,14308,14310,14312],{"class":72,"line":1736},[70,14295,8223],{"class":219},[70,14297,8226],{"class":76},[70,14299,265],{"class":264},[70,14301,5601],{"class":219},[70,14303,7871],{"class":76},[70,14305,386],{"class":264},[70,14307,3196],{"class":76},[70,14309,4549],{"class":219},[70,14311,3199],{"class":270},[70,14313,337],{"class":264},[70,14315,14316],{"class":72,"line":1741},[70,14317,343],{"class":264},[70,14319,14320],{"class":72,"line":1748},[70,14321,14322],{"class":295},"        \u002F\u002F main 线程不直接修改 write_queue_。\n",[70,14324,14325],{"class":72,"line":1753},[70,14326,14327],{"class":295},"        \u002F\u002F 只把“加入发送队列”这个任务投递给 Asio 线程。\n",[70,14329,14330,14332,14334,14336,14338,14340],{"class":72,"line":1773},[70,14331,626],{"class":76},[70,14333,386],{"class":264},[70,14335,389],{"class":76},[70,14337,386],{"class":264},[70,14339,14251],{"class":76},[70,14341,620],{"class":264},[70,14343,14344],{"class":72,"line":1782},[70,14345,14258],{"class":264},[70,14347,14348,14350,14352,14354],{"class":72,"line":1787},[70,14349,5156],{"class":76},[70,14351,386],{"class":264},[70,14353,5144],{"class":76},[70,14355,620],{"class":264},[70,14357,14358,14360,14362],{"class":72,"line":1792},[70,14359,8461],{"class":219},[70,14361,12464],{"class":76},[70,14363,14364],{"class":264},"::enqueue_write,\n",[70,14366,14367,14369],{"class":72,"line":1798},[70,14368,8472],{"class":124},[70,14370,4555],{"class":264},[70,14372,14373],{"class":72,"line":1818},[70,14374,14375],{"class":264},"                msg));\n",[70,14377,14378],{"class":72,"line":1823},[70,14379,366],{"class":264},[70,14381,14382],{"class":72,"line":1839},[70,14383,252],{"emptyLinePlaceholder":251},[70,14385,14386,14388,14391],{"class":72,"line":1856},[70,14387,8223],{"class":219},[70,14389,14390],{"class":76}," stop",[70,14392,3162],{"class":264},[70,14394,14395],{"class":72,"line":1861},[70,14396,343],{"class":264},[70,14398,14399],{"class":72,"line":1876},[70,14400,14401],{"class":295},"        \u002F\u002F 停止操作也交给 Asio 线程完成。\n",[70,14403,14404,14406,14408,14410,14412,14414],{"class":72,"line":1881},[70,14405,626],{"class":76},[70,14407,386],{"class":264},[70,14409,389],{"class":76},[70,14411,386],{"class":264},[70,14413,14251],{"class":76},[70,14415,620],{"class":264},[70,14417,14418],{"class":72,"line":1890},[70,14419,14258],{"class":264},[70,14421,14422,14424,14426,14428],{"class":72,"line":5216},[70,14423,5156],{"class":76},[70,14425,386],{"class":264},[70,14427,5144],{"class":76},[70,14429,620],{"class":264},[70,14431,14432,14434,14436],{"class":72,"line":5221},[70,14433,8461],{"class":219},[70,14435,12464],{"class":76},[70,14437,14438],{"class":264},"::do_stop,\n",[70,14440,14441,14443],{"class":72,"line":5231},[70,14442,8472],{"class":124},[70,14444,562],{"class":264},[70,14446,14447],{"class":72,"line":5236},[70,14448,366],{"class":264},[70,14450,14451],{"class":72,"line":5252},[70,14452,252],{"emptyLinePlaceholder":251},[70,14454,14455],{"class":72,"line":5267},[70,14456,8384],{"class":219},[70,14458,14459,14461,14463],{"class":72,"line":5272},[70,14460,8223],{"class":219},[70,14462,10217],{"class":76},[70,14464,3162],{"class":264},[70,14466,14467],{"class":72,"line":5281},[70,14468,343],{"class":264},[70,14470,14471,14473,14476,14479,14481,14484,14487],{"class":72,"line":6936},[70,14472,7929],{"class":219},[70,14474,14475],{"class":264}," (stopping_ ",[70,14477,14478],{"class":219},"||",[70,14480,8269],{"class":219},[70,14482,14483],{"class":264},"serial_.",[70,14485,14486],{"class":76},"is_open",[70,14488,8674],{"class":264},[70,14490,14491],{"class":72,"line":6941},[70,14492,7936],{"class":264},[70,14494,14495,14497],{"class":72,"line":6950},[70,14496,7971],{"class":219},[70,14498,314],{"class":264},[70,14500,14501],{"class":72,"line":6955},[70,14502,7978],{"class":264},[70,14504,14505],{"class":72,"line":6970},[70,14506,252],{"emptyLinePlaceholder":251},[70,14508,14509,14511,14513,14515],{"class":72,"line":6985},[70,14510,488],{"class":76},[70,14512,386],{"class":264},[70,14514,444],{"class":76},[70,14516,620],{"class":264},[70,14518,14519,14522],{"class":72,"line":6990},[70,14520,14521],{"class":80},"            \"Asio线程：等待下一组 11 字节\"",[70,14523,898],{"class":264},[70,14525,14526],{"class":72,"line":6999},[70,14527,252],{"emptyLinePlaceholder":251},[70,14529,14530,14532,14534,14536,14538,14540],{"class":72,"line":8599},[70,14531,626],{"class":76},[70,14533,386],{"class":264},[70,14535,389],{"class":76},[70,14537,386],{"class":264},[70,14539,6084],{"class":76},[70,14541,620],{"class":264},[70,14543,14544],{"class":72,"line":8604},[70,14545,8421],{"class":264},[70,14547,14548,14550,14552,14554,14556,14558],{"class":72,"line":8615},[70,14549,1496],{"class":76},[70,14551,386],{"class":264},[70,14553,389],{"class":76},[70,14555,386],{"class":264},[70,14557,810],{"class":76},[70,14559,12447],{"class":264},[70,14561,14562,14564,14566,14568],{"class":72,"line":8623},[70,14563,5156],{"class":76},[70,14565,386],{"class":264},[70,14567,5144],{"class":76},[70,14569,620],{"class":264},[70,14571,14572,14574,14576],{"class":72,"line":8629},[70,14573,8461],{"class":219},[70,14575,12464],{"class":76},[70,14577,10297],{"class":264},[70,14579,14580,14582],{"class":72,"line":8634},[70,14581,8472],{"class":124},[70,14583,4555],{"class":264},[70,14585,14586,14588,14590,14592],{"class":72,"line":8640},[70,14587,8479],{"class":76},[70,14589,386],{"class":264},[70,14591,5161],{"class":76},[70,14593,5164],{"class":264},[70,14595,14596,14598,14600,14602],{"class":72,"line":8650},[70,14597,8479],{"class":76},[70,14599,386],{"class":264},[70,14601,5161],{"class":76},[70,14603,5175],{"class":264},[70,14605,14606],{"class":72,"line":8655},[70,14607,366],{"class":264},[70,14609,14610],{"class":72,"line":8661},[70,14611,252],{"emptyLinePlaceholder":251},[70,14613,14614,14616,14618],{"class":72,"line":8677},[70,14615,8223],{"class":219},[70,14617,6181],{"class":76},[70,14619,620],{"class":264},[70,14621,14622,14624,14626,14628,14630,14632,14634,14636,14638],{"class":72,"line":8682},[70,14623,7868],{"class":219},[70,14625,787],{"class":76},[70,14627,386],{"class":264},[70,14629,426],{"class":76},[70,14631,386],{"class":264},[70,14633,4546],{"class":76},[70,14635,4549],{"class":219},[70,14637,4552],{"class":270},[70,14639,4555],{"class":264},[70,14641,14642,14644,14646,14648,14650],{"class":72,"line":8689},[70,14643,488],{"class":76},[70,14645,386],{"class":264},[70,14647,779],{"class":219},[70,14649,4566],{"class":270},[70,14651,337],{"class":264},[70,14653,14654],{"class":72,"line":8694},[70,14655,343],{"class":264},[70,14657,14658,14660],{"class":72,"line":8699},[70,14659,7929],{"class":219},[70,14661,477],{"class":264},[70,14663,14664],{"class":72,"line":8704},[70,14665,7936],{"class":264},[70,14667,14668,14670,14672,14674],{"class":72,"line":8709},[70,14669,5156],{"class":76},[70,14671,386],{"class":264},[70,14673,444],{"class":76},[70,14675,620],{"class":264},[70,14677,14678,14681],{"class":72,"line":8721},[70,14679,14680],{"class":80},"                \"读取结束：{}\"",[70,14682,4555],{"class":264},[70,14684,14685,14687,14689],{"class":72,"line":8726},[70,14686,7958],{"class":264},[70,14688,503],{"class":76},[70,14690,506],{"class":264},[70,14692,14693],{"class":72,"line":8732},[70,14694,252],{"emptyLinePlaceholder":251},[70,14696,14697,14699],{"class":72,"line":8752},[70,14698,7971],{"class":219},[70,14700,314],{"class":264},[70,14702,14703],{"class":72,"line":8758},[70,14704,7978],{"class":264},[70,14706,14707],{"class":72,"line":8763},[70,14708,252],{"emptyLinePlaceholder":251},[70,14710,14711,14713,14715,14717],{"class":72,"line":8784},[70,14712,488],{"class":76},[70,14714,1803],{"class":264},[70,14716,1806],{"class":76},[70,14718,620],{"class":264},[70,14720,14721,14723,14725],{"class":72,"line":8789},[70,14722,12612],{"class":264},[70,14724,1812],{"class":76},[70,14726,6310],{"class":264},[70,14728,14729],{"class":72,"line":8802},[70,14730,8626],{"class":264},[70,14732,14733],{"class":72,"line":8807},[70,14734,252],{"emptyLinePlaceholder":251},[70,14736,14737,14739,14741,14743],{"class":72,"line":8820},[70,14738,488],{"class":76},[70,14740,386],{"class":264},[70,14742,444],{"class":76},[70,14744,620],{"class":264},[70,14746,14747,14750],{"class":72,"line":8825},[70,14748,14749],{"class":80},"            \"Asio线程：收到数据，字节数 = {}，内容 = {}\"",[70,14751,4555],{"class":264},[70,14753,14754],{"class":72,"line":8838},[70,14755,10477],{"class":264},[70,14757,14758],{"class":72,"line":8843},[70,14759,8329],{"class":264},[70,14761,14762],{"class":72,"line":8848},[70,14763,252],{"emptyLinePlaceholder":251},[70,14765,14766,14768,14770,14772],{"class":72,"line":8859},[70,14767,7929],{"class":219},[70,14769,8350],{"class":264},[70,14771,8353],{"class":219},[70,14773,14774],{"class":264},"stopping_)\n",[70,14776,14777],{"class":72,"line":8864},[70,14778,7936],{"class":264},[70,14780,14781,14784],{"class":72,"line":8876},[70,14782,14783],{"class":76},"            start_read",[70,14785,2240],{"class":264},[70,14787,14788],{"class":72,"line":8881},[70,14789,7978],{"class":264},[70,14791,14792],{"class":72,"line":8899},[70,14793,366],{"class":264},[70,14795,14796],{"class":72,"line":8916},[70,14797,252],{"emptyLinePlaceholder":251},[70,14799,14800,14802,14805,14807,14809,14811,14813,14815],{"class":72,"line":8933},[70,14801,8223],{"class":219},[70,14803,14804],{"class":76}," enqueue_write",[70,14806,265],{"class":264},[70,14808,2058],{"class":76},[70,14810,386],{"class":264},[70,14812,3196],{"class":76},[70,14814,3199],{"class":270},[70,14816,337],{"class":264},[70,14818,14819],{"class":72,"line":8938},[70,14820,343],{"class":264},[70,14822,14823,14825],{"class":72,"line":8953},[70,14824,7929],{"class":219},[70,14826,14827],{"class":264}," (stopping_)\n",[70,14829,14830],{"class":72,"line":8958},[70,14831,7936],{"class":264},[70,14833,14834,14836],{"class":72,"line":8967},[70,14835,7971],{"class":219},[70,14837,314],{"class":264},[70,14839,14840],{"class":72,"line":8972},[70,14841,7978],{"class":264},[70,14843,14844],{"class":72,"line":8983},[70,14845,252],{"emptyLinePlaceholder":251},[70,14847,14848,14850,14852,14854,14856,14858,14860],{"class":72,"line":8991},[70,14849,8261],{"class":219},[70,14851,8264],{"class":264},[70,14853,308],{"class":219},[70,14855,8269],{"class":219},[70,14857,8272],{"class":264},[70,14859,8275],{"class":76},[70,14861,2240],{"class":264},[70,14863,14864],{"class":72,"line":8996},[70,14865,252],{"emptyLinePlaceholder":251},[70,14867,14868,14870,14872],{"class":72,"line":9005},[70,14869,8296],{"class":264},[70,14871,8299],{"class":76},[70,14873,8302],{"class":264},[70,14875,14876],{"class":72,"line":12894},[70,14877,252],{"emptyLinePlaceholder":251},[70,14879,14880,14882,14884,14886],{"class":72,"line":12899},[70,14881,488],{"class":76},[70,14883,386],{"class":264},[70,14885,8315],{"class":76},[70,14887,620],{"class":264},[70,14889,14890,14893],{"class":72,"line":12904},[70,14891,14892],{"class":80},"            \"Asio线程：加入发送队列：{}\"",[70,14894,4555],{"class":264},[70,14896,14897],{"class":72,"line":12910},[70,14898,8329],{"class":264},[70,14900,14901],{"class":72,"line":12919},[70,14902,252],{"emptyLinePlaceholder":251},[70,14904,14905,14907,14909,14911],{"class":72,"line":12924},[70,14906,7929],{"class":219},[70,14908,8350],{"class":264},[70,14910,8353],{"class":219},[70,14912,8356],{"class":264},[70,14914,14915],{"class":72,"line":12930},[70,14916,7936],{"class":264},[70,14918,14919,14921],{"class":72,"line":12945},[70,14920,8365],{"class":76},[70,14922,2240],{"class":264},[70,14924,14925],{"class":72,"line":12950},[70,14926,7978],{"class":264},[70,14928,14929],{"class":72,"line":12957},[70,14930,366],{"class":264},[70,14932,14933],{"class":72,"line":12962},[70,14934,252],{"emptyLinePlaceholder":251},[70,14936,14937,14939,14941],{"class":72,"line":12967},[70,14938,8223],{"class":219},[70,14940,8391],{"class":76},[70,14942,3162],{"class":264},[70,14944,14945],{"class":72,"line":12972},[70,14946,343],{"class":264},[70,14948,14949,14951,14953,14955,14958,14960],{"class":72,"line":12977},[70,14950,7929],{"class":219},[70,14952,14475],{"class":264},[70,14954,14478],{"class":219},[70,14956,14957],{"class":264}," write_queue_.",[70,14959,8275],{"class":76},[70,14961,8674],{"class":264},[70,14963,14964],{"class":72,"line":12988},[70,14965,7936],{"class":264},[70,14967,14968,14970],{"class":72,"line":12993},[70,14969,7971],{"class":219},[70,14971,314],{"class":264},[70,14973,14974],{"class":72,"line":12998},[70,14975,7978],{"class":264},[70,14977,14978],{"class":72,"line":13016},[70,14979,252],{"emptyLinePlaceholder":251},[70,14981,14982,14984,14986,14988,14990,14992],{"class":72,"line":13021},[70,14983,626],{"class":76},[70,14985,386],{"class":264},[70,14987,389],{"class":76},[70,14989,386],{"class":264},[70,14991,4446],{"class":76},[70,14993,620],{"class":264},[70,14995,14996],{"class":72,"line":13027},[70,14997,8421],{"class":264},[70,14999,15000,15002,15004,15006,15008,15010],{"class":72,"line":13044},[70,15001,1496],{"class":76},[70,15003,386],{"class":264},[70,15005,389],{"class":76},[70,15007,386],{"class":264},[70,15009,810],{"class":76},[70,15011,620],{"class":264},[70,15013,15014,15016,15018],{"class":72,"line":13049},[70,15015,8440],{"class":264},[70,15017,8443],{"class":76},[70,15019,8446],{"class":264},[70,15021,15022,15024,15026,15028],{"class":72,"line":13054},[70,15023,5156],{"class":76},[70,15025,386],{"class":264},[70,15027,5144],{"class":76},[70,15029,620],{"class":264},[70,15031,15032,15034,15036],{"class":72,"line":13075},[70,15033,8461],{"class":219},[70,15035,12464],{"class":76},[70,15037,8467],{"class":264},[70,15039,15040,15042],{"class":72,"line":13080},[70,15041,8472],{"class":124},[70,15043,4555],{"class":264},[70,15045,15046,15048,15050,15052],{"class":72,"line":13093},[70,15047,8479],{"class":76},[70,15049,386],{"class":264},[70,15051,5161],{"class":76},[70,15053,5164],{"class":264},[70,15055,15056,15058,15060,15062],{"class":72,"line":13098},[70,15057,8479],{"class":76},[70,15059,386],{"class":264},[70,15061,5161],{"class":76},[70,15063,5175],{"class":264},[70,15065,15066],{"class":72,"line":13111},[70,15067,366],{"class":264},[70,15069,15070],{"class":72,"line":13116},[70,15071,252],{"emptyLinePlaceholder":251},[70,15073,15074,15076,15078],{"class":72,"line":13129},[70,15075,8223],{"class":219},[70,15077,4528],{"class":76},[70,15079,620],{"class":264},[70,15081,15082,15084,15086,15088,15090,15092,15094,15096,15098],{"class":72,"line":13134},[70,15083,7868],{"class":219},[70,15085,787],{"class":76},[70,15087,386],{"class":264},[70,15089,426],{"class":76},[70,15091,386],{"class":264},[70,15093,4546],{"class":76},[70,15095,4549],{"class":219},[70,15097,4552],{"class":270},[70,15099,4555],{"class":264},[70,15101,15102,15104,15106,15108,15110],{"class":72,"line":13139},[70,15103,488],{"class":76},[70,15105,386],{"class":264},[70,15107,779],{"class":219},[70,15109,4566],{"class":270},[70,15111,337],{"class":264},[70,15113,15114],{"class":72,"line":13150},[70,15115,343],{"class":264},[70,15117,15118,15120],{"class":72,"line":13155},[70,15119,7929],{"class":219},[70,15121,477],{"class":264},[70,15123,15124],{"class":72,"line":13165},[70,15125,7936],{"class":264},[70,15127,15128,15130,15132,15134],{"class":72,"line":13170},[70,15129,5156],{"class":76},[70,15131,386],{"class":264},[70,15133,444],{"class":76},[70,15135,620],{"class":264},[70,15137,15138,15141],{"class":72,"line":13176},[70,15139,15140],{"class":80},"                \"发送结束：{}\"",[70,15142,4555],{"class":264},[70,15144,15145,15147,15149],{"class":72,"line":13193},[70,15146,7958],{"class":264},[70,15148,503],{"class":76},[70,15150,506],{"class":264},[70,15152,15153],{"class":72,"line":13210},[70,15154,252],{"emptyLinePlaceholder":251},[70,15156,15157,15159],{"class":72,"line":13227},[70,15158,7971],{"class":219},[70,15160,314],{"class":264},[70,15162,15163],{"class":72,"line":13232},[70,15164,7978],{"class":264},[70,15166,15167],{"class":72,"line":13243},[70,15168,252],{"emptyLinePlaceholder":251},[70,15170,15171,15173,15175,15177],{"class":72,"line":13251},[70,15172,488],{"class":76},[70,15174,386],{"class":264},[70,15176,444],{"class":76},[70,15178,620],{"class":264},[70,15180,15181,15184],{"class":72,"line":13256},[70,15182,15183],{"class":80},"            \"Asio线程：发送完成，字节数 = {}\"",[70,15185,4555],{"class":264},[70,15187,15188],{"class":72,"line":13265},[70,15189,8626],{"class":264},[70,15191,15192],{"class":72,"line":13270},[70,15193,252],{"emptyLinePlaceholder":251},[70,15195,15196,15198,15200],{"class":72,"line":13285},[70,15197,8296],{"class":264},[70,15199,8645],{"class":76},[70,15201,2240],{"class":264},[70,15203,15204],{"class":72,"line":13290},[70,15205,252],{"emptyLinePlaceholder":251},[70,15207,15208,15210,15212,15214,15216,15218],{"class":72,"line":13299},[70,15209,7929],{"class":219},[70,15211,8350],{"class":264},[70,15213,8353],{"class":219},[70,15215,8272],{"class":264},[70,15217,8275],{"class":76},[70,15219,8674],{"class":264},[70,15221,15223],{"class":72,"line":15222},196,[70,15224,7936],{"class":264},[70,15226,15228,15230],{"class":72,"line":15227},197,[70,15229,8365],{"class":76},[70,15231,2240],{"class":264},[70,15233,15235],{"class":72,"line":15234},198,[70,15236,7978],{"class":264},[70,15238,15240],{"class":72,"line":15239},199,[70,15241,366],{"class":264},[70,15243,15245],{"class":72,"line":15244},200,[70,15246,252],{"emptyLinePlaceholder":251},[70,15248,15250,15252,15255],{"class":72,"line":15249},201,[70,15251,8223],{"class":219},[70,15253,15254],{"class":76}," do_stop",[70,15256,3162],{"class":264},[70,15258,15260],{"class":72,"line":15259},202,[70,15261,343],{"class":264},[70,15263,15265,15267],{"class":72,"line":15264},203,[70,15266,7929],{"class":219},[70,15268,14827],{"class":264},[70,15270,15272],{"class":72,"line":15271},204,[70,15273,7936],{"class":264},[70,15275,15277,15279],{"class":72,"line":15276},205,[70,15278,7971],{"class":219},[70,15280,314],{"class":264},[70,15282,15284],{"class":72,"line":15283},206,[70,15285,7978],{"class":264},[70,15287,15289],{"class":72,"line":15288},207,[70,15290,252],{"emptyLinePlaceholder":251},[70,15292,15294,15297,15299,15302],{"class":72,"line":15293},208,[70,15295,15296],{"class":264},"        stopping_ ",[70,15298,308],{"class":219},[70,15300,15301],{"class":124}," true",[70,15303,314],{"class":264},[70,15305,15307],{"class":72,"line":15306},209,[70,15308,252],{"emptyLinePlaceholder":251},[70,15310,15312,15314,15316,15318],{"class":72,"line":15311},210,[70,15313,488],{"class":76},[70,15315,386],{"class":264},[70,15317,444],{"class":76},[70,15319,620],{"class":264},[70,15321,15323,15326],{"class":72,"line":15322},211,[70,15324,15325],{"class":80},"            \"Asio线程：开始关闭串口\"",[70,15327,898],{"class":264},[70,15329,15331],{"class":72,"line":15330},212,[70,15332,252],{"emptyLinePlaceholder":251},[70,15334,15336,15338,15340,15342],{"class":72,"line":15335},213,[70,15337,626],{"class":76},[70,15339,386],{"class":264},[70,15341,426],{"class":76},[70,15343,429],{"class":264},[70,15345,15347],{"class":72,"line":15346},214,[70,15348,252],{"emptyLinePlaceholder":251},[70,15350,15352,15354,15357],{"class":72,"line":15351},215,[70,15353,7916],{"class":264},[70,15355,15356],{"class":76},"cancel",[70,15358,15359],{"class":264},"(ec);\n",[70,15361,15363],{"class":72,"line":15362},216,[70,15364,252],{"emptyLinePlaceholder":251},[70,15366,15368,15371,15374],{"class":72,"line":15367},217,[70,15369,15370],{"class":264},"        ec.",[70,15372,15373],{"class":76},"clear",[70,15375,2240],{"class":264},[70,15377,15379],{"class":72,"line":15378},218,[70,15380,252],{"emptyLinePlaceholder":251},[70,15382,15384,15386,15389],{"class":72,"line":15383},219,[70,15385,7916],{"class":264},[70,15387,15388],{"class":76},"close",[70,15390,15359],{"class":264},[70,15392,15394],{"class":72,"line":15393},220,[70,15395,366],{"class":264},[70,15397,15399],{"class":72,"line":15398},221,[70,15400,252],{"emptyLinePlaceholder":251},[70,15402,15404],{"class":72,"line":15403},222,[70,15405,8384],{"class":219},[70,15407,15409,15411,15413,15415,15418,15420],{"class":72,"line":15408},223,[70,15410,383],{"class":76},[70,15412,386],{"class":264},[70,15414,389],{"class":76},[70,15416,15417],{"class":264},"::io_context",[70,15419,4549],{"class":219},[70,15421,15422],{"class":264}," io_;\n",[70,15424,15426],{"class":72,"line":15425},224,[70,15427,252],{"emptyLinePlaceholder":251},[70,15429,15431,15433,15435,15437],{"class":72,"line":15430},225,[70,15432,383],{"class":76},[70,15434,386],{"class":264},[70,15436,389],{"class":76},[70,15438,8718],{"class":264},[70,15440,15442],{"class":72,"line":15441},226,[70,15443,252],{"emptyLinePlaceholder":251},[70,15445,15447,15449,15451,15453,15455,15457,15459],{"class":72,"line":15446},227,[70,15448,302],{"class":76},[70,15450,1623],{"class":264},[70,15452,1626],{"class":219},[70,15454,274],{"class":264},[70,15456,1631],{"class":124},[70,15458,1634],{"class":219},[70,15460,13013],{"class":264},[70,15462,15464],{"class":72,"line":15463},228,[70,15465,252],{"emptyLinePlaceholder":251},[70,15467,15469,15471,15473,15475,15477,15479,15481],{"class":72,"line":15468},229,[70,15470,302],{"class":76},[70,15472,8737],{"class":264},[70,15474,6226],{"class":219},[70,15476,2058],{"class":76},[70,15478,8744],{"class":264},[70,15480,1634],{"class":219},[70,15482,8749],{"class":264},[70,15484,15486],{"class":72,"line":15485},230,[70,15487,252],{"emptyLinePlaceholder":251},[70,15489,15491,15494,15497,15499,15502],{"class":72,"line":15490},231,[70,15492,15493],{"class":219},"    bool",[70,15495,15496],{"class":264}," stopping_ ",[70,15498,308],{"class":219},[70,15500,15501],{"class":124}," false",[70,15503,314],{"class":264},[70,15505,15507],{"class":72,"line":15506},232,[70,15508,8755],{"class":264},[70,15510,15512],{"class":72,"line":15511},233,[70,15513,252],{"emptyLinePlaceholder":251},[70,15515,15517,15519,15522,15524,15526,15528,15530,15532,15534,15536,15538],{"class":72,"line":15516},234,[70,15518,4525],{"class":219},[70,15520,15521],{"class":76}," run_io",[70,15523,265],{"class":264},[70,15525,540],{"class":76},[70,15527,386],{"class":264},[70,15529,389],{"class":76},[70,15531,386],{"class":264},[70,15533,7856],{"class":76},[70,15535,6238],{"class":219},[70,15537,7861],{"class":270},[70,15539,337],{"class":264},[70,15541,15543],{"class":72,"line":15542},235,[70,15544,289],{"class":264},[70,15546,15548,15550,15552,15554],{"class":72,"line":15547},236,[70,15549,302],{"class":76},[70,15551,386],{"class":264},[70,15553,444],{"class":76},[70,15555,620],{"class":264},[70,15557,15559,15562],{"class":72,"line":15558},237,[70,15560,15561],{"class":80},"        \"Asio线程：开始 io.run()，线程 id = {}\"",[70,15563,4555],{"class":264},[70,15565,15567,15569,15571,15574,15576,15579],{"class":72,"line":15566},238,[70,15568,488],{"class":76},[70,15570,386],{"class":264},[70,15572,15573],{"class":76},"this_thread",[70,15575,386],{"class":264},[70,15577,15578],{"class":76},"get_id",[70,15580,506],{"class":264},[70,15582,15584],{"class":72,"line":15583},239,[70,15585,252],{"emptyLinePlaceholder":251},[70,15587,15589,15592,15594],{"class":72,"line":15588},240,[70,15590,15591],{"class":264},"    io->",[70,15593,2237],{"class":76},[70,15595,2240],{"class":264},[70,15597,15599],{"class":72,"line":15598},241,[70,15600,252],{"emptyLinePlaceholder":251},[70,15602,15604,15606,15608,15610],{"class":72,"line":15603},242,[70,15605,302],{"class":76},[70,15607,386],{"class":264},[70,15609,444],{"class":76},[70,15611,620],{"class":264},[70,15613,15615,15618],{"class":72,"line":15614},243,[70,15616,15617],{"class":80},"        \"Asio线程：io.run() 返回\"",[70,15619,898],{"class":264},[70,15621,15623],{"class":72,"line":15622},244,[70,15624,920],{"class":264},[70,15626,15628],{"class":72,"line":15627},245,[70,15629,252],{"emptyLinePlaceholder":251},[70,15631,15633,15635,15637,15639,15641,15643,15645,15647,15649],{"class":72,"line":15632},246,[70,15634,258],{"class":219},[70,15636,261],{"class":76},[70,15638,265],{"class":264},[70,15640,258],{"class":219},[70,15642,271],{"class":270},[70,15644,274],{"class":264},[70,15646,277],{"class":219},[70,15648,280],{"class":270},[70,15650,283],{"class":264},[70,15652,15654],{"class":72,"line":15653},247,[70,15655,289],{"class":264},[70,15657,15659,15661,15663,15665,15667],{"class":72,"line":15658},248,[70,15660,302],{"class":76},[70,15662,305],{"class":264},[70,15664,308],{"class":219},[70,15666,311],{"class":80},[70,15668,314],{"class":264},[70,15670,15672],{"class":72,"line":15671},249,[70,15673,252],{"emptyLinePlaceholder":251},[70,15675,15677,15679,15681,15683,15685],{"class":72,"line":15676},250,[70,15678,325],{"class":219},[70,15680,328],{"class":264},[70,15682,331],{"class":219},[70,15684,334],{"class":124},[70,15686,337],{"class":264},[70,15688,15690],{"class":72,"line":15689},251,[70,15691,343],{"class":264},[70,15693,15695,15697,15699,15701,15703],{"class":72,"line":15694},252,[70,15696,349],{"class":264},[70,15698,308],{"class":219},[70,15700,354],{"class":264},[70,15702,357],{"class":124},[70,15704,360],{"class":264},[70,15706,15708],{"class":72,"line":15707},253,[70,15709,366],{"class":264},[70,15711,15713],{"class":72,"line":15712},254,[70,15714,252],{"emptyLinePlaceholder":251},[70,15716,15718,15720,15722,15724],{"class":72,"line":15717},255,[70,15719,383],{"class":76},[70,15721,386],{"class":264},[70,15723,389],{"class":76},[70,15725,392],{"class":264},[70,15727,15729],{"class":72,"line":15728},256,[70,15730,252],{"emptyLinePlaceholder":251},[70,15732,15734],{"class":72,"line":15733},257,[70,15735,15736],{"class":295},"    \u002F\u002F 保证 Asio 后台线程即使暂时没有任务，\n",[70,15738,15740],{"class":72,"line":15739},258,[70,15741,15742],{"class":295},"    \u002F\u002F io.run() 也不会立刻返回。\n",[70,15744,15746,15749,15752],{"class":72,"line":15745},259,[70,15747,15748],{"class":219},"    auto",[70,15750,15751],{"class":264}," guard ",[70,15753,1689],{"class":219},[70,15755,15757,15759,15761,15763,15765,15768],{"class":72,"line":15756},260,[70,15758,626],{"class":76},[70,15760,386],{"class":264},[70,15762,389],{"class":76},[70,15764,386],{"class":264},[70,15766,15767],{"class":76},"make_work_guard",[70,15769,416],{"class":264},[70,15771,15773],{"class":72,"line":15772},261,[70,15774,252],{"emptyLinePlaceholder":251},[70,15776,15778,15780,15782],{"class":72,"line":15777},262,[70,15779,13158],{"class":264},[70,15781,413],{"class":76},[70,15783,8873],{"class":264},[70,15785,15787],{"class":72,"line":15786},263,[70,15788,252],{"emptyLinePlaceholder":251},[70,15790,15792],{"class":72,"line":15791},264,[70,15793,15794],{"class":295},"    \u002F\u002F 单独创建一个线程运行 Asio 事件循环。\n",[70,15796,15798,15800,15803,15806],{"class":72,"line":15797},265,[70,15799,302],{"class":76},[70,15801,15802],{"class":264},"::thread ",[70,15804,15805],{"class":76},"io_thread",[70,15807,620],{"class":264},[70,15809,15811,15813,15815,15817],{"class":72,"line":15810},266,[70,15812,488],{"class":76},[70,15814,386],{"class":264},[70,15816,5144],{"class":76},[70,15818,620],{"class":264},[70,15820,15822],{"class":72,"line":15821},267,[70,15823,15824],{"class":264},"            run_io,\n",[70,15826,15828,15830],{"class":72,"line":15827},268,[70,15829,6893],{"class":219},[70,15831,15832],{"class":264},"io));\n",[70,15834,15836],{"class":72,"line":15835},269,[70,15837,252],{"emptyLinePlaceholder":251},[70,15839,15841],{"class":72,"line":15840},270,[70,15842,15843],{"class":295},"    \u002F\u002F 此时 Asio 线程已经可能进入 io.run()。\n",[70,15845,15847],{"class":72,"line":15846},271,[70,15848,15849],{"class":295},"    \u002F\u002F start() 把第一次读取任务投递给 Asio 线程。\n",[70,15851,15853,15855,15858],{"class":72,"line":15852},272,[70,15854,463],{"class":264},[70,15856,15857],{"class":76},"start",[70,15859,2240],{"class":264},[70,15861,15863],{"class":72,"line":15862},273,[70,15864,252],{"emptyLinePlaceholder":251},[70,15866,15868,15870,15872,15874],{"class":72,"line":15867},274,[70,15869,302],{"class":76},[70,15871,386],{"class":264},[70,15873,444],{"class":76},[70,15875,620],{"class":264},[70,15877,15879,15882],{"class":72,"line":15878},275,[70,15880,15881],{"class":80},"        \"main线程 id = {}\"",[70,15883,4555],{"class":264},[70,15885,15887,15889,15891,15893,15895,15897],{"class":72,"line":15886},276,[70,15888,488],{"class":76},[70,15890,386],{"class":264},[70,15892,15573],{"class":76},[70,15894,386],{"class":264},[70,15896,15578],{"class":76},[70,15898,506],{"class":264},[70,15900,15902],{"class":72,"line":15901},277,[70,15903,252],{"emptyLinePlaceholder":251},[70,15905,15907],{"class":72,"line":15906},278,[70,15908,15909],{"class":295},"    \u002F\u002F 模拟 main 中的其他业务逻辑不断产生待发送数据。\n",[70,15911,15913,15915,15917,15919,15921,15923,15925],{"class":72,"line":15912},279,[70,15914,463],{"class":264},[70,15916,7685],{"class":76},[70,15918,265],{"class":264},[70,15920,7690],{"class":80},[70,15922,753],{"class":124},[70,15924,756],{"class":80},[70,15926,898],{"class":264},[70,15928,15930,15932,15934,15936,15938,15940,15942],{"class":72,"line":15929},280,[70,15931,463],{"class":264},[70,15933,7685],{"class":76},[70,15935,265],{"class":264},[70,15937,7705],{"class":80},[70,15939,753],{"class":124},[70,15941,756],{"class":80},[70,15943,898],{"class":264},[70,15945,15947,15949,15951,15953,15955,15957,15959],{"class":72,"line":15946},281,[70,15948,463],{"class":264},[70,15950,7685],{"class":76},[70,15952,265],{"class":264},[70,15954,7720],{"class":80},[70,15956,753],{"class":124},[70,15958,756],{"class":80},[70,15960,898],{"class":264},[70,15962,15964],{"class":72,"line":15963},282,[70,15965,252],{"emptyLinePlaceholder":251},[70,15967,15969,15971,15973,15975],{"class":72,"line":15968},283,[70,15970,302],{"class":76},[70,15972,386],{"class":264},[70,15974,444],{"class":76},[70,15976,620],{"class":264},[70,15978,15980,15983],{"class":72,"line":15979},284,[70,15981,15982],{"class":80},"        \"main：数据已经提交给 Asio，main 可以继续处理其他工作\"",[70,15984,898],{"class":264},[70,15986,15988],{"class":72,"line":15987},285,[70,15989,252],{"emptyLinePlaceholder":251},[70,15991,15993,15995,15997,15999],{"class":72,"line":15992},286,[70,15994,302],{"class":76},[70,15996,386],{"class":264},[70,15998,444],{"class":76},[70,16000,620],{"class":264},[70,16002,16004,16007],{"class":72,"line":16003},287,[70,16005,16006],{"class":80},"        \"main：按 Enter 结束程序\"",[70,16008,898],{"class":264},[70,16010,16012],{"class":72,"line":16011},288,[70,16013,252],{"emptyLinePlaceholder":251},[70,16015,16017,16019],{"class":72,"line":16016},289,[70,16018,302],{"class":76},[70,16020,16021],{"class":264},"::string input;\n",[70,16023,16025,16027,16029,16032,16034,16036],{"class":72,"line":16024},290,[70,16026,302],{"class":76},[70,16028,386],{"class":264},[70,16030,16031],{"class":76},"getline",[70,16033,265],{"class":264},[70,16035,2058],{"class":76},[70,16037,16038],{"class":264},"::cin, input);\n",[70,16040,16042],{"class":72,"line":16041},291,[70,16043,252],{"emptyLinePlaceholder":251},[70,16045,16047],{"class":72,"line":16046},292,[70,16048,16049],{"class":295},"    \u002F\u002F 把关闭串口任务投递给 Asio 线程。\n",[70,16051,16053,16055,16058],{"class":72,"line":16052},293,[70,16054,463],{"class":264},[70,16056,16057],{"class":76},"stop",[70,16059,2240],{"class":264},[70,16061,16063],{"class":72,"line":16062},294,[70,16064,252],{"emptyLinePlaceholder":251},[70,16066,16068],{"class":72,"line":16067},295,[70,16069,16070],{"class":295},"    \u002F\u002F 允许 io.run() 在剩余任务处理完成后自然返回。\n",[70,16072,16074,16077,16080],{"class":72,"line":16073},296,[70,16075,16076],{"class":264},"    guard.",[70,16078,16079],{"class":76},"reset",[70,16081,2240],{"class":264},[70,16083,16085],{"class":72,"line":16084},297,[70,16086,252],{"emptyLinePlaceholder":251},[70,16088,16090,16093,16096],{"class":72,"line":16089},298,[70,16091,16092],{"class":264},"    io_thread.",[70,16094,16095],{"class":76},"join",[70,16097,2240],{"class":264},[70,16099,16101],{"class":72,"line":16100},299,[70,16102,252],{"emptyLinePlaceholder":251},[70,16104,16106,16108,16110,16112,16114,16116],{"class":72,"line":16105},300,[70,16107,302],{"class":76},[70,16109,386],{"class":264},[70,16111,444],{"class":76},[70,16113,265],{"class":264},[70,16115,895],{"class":80},[70,16117,898],{"class":264},[70,16119,16121],{"class":72,"line":16120},301,[70,16122,252],{"emptyLinePlaceholder":251},[70,16124,16126,16128,16130],{"class":72,"line":16125},302,[70,16127,909],{"class":219},[70,16129,912],{"class":124},[70,16131,314],{"class":264},[70,16133,16135],{"class":72,"line":16134},303,[70,16136,920],{"class":264},[55,16138,930],{"id":16139},"编译运行-7",[15,16141,9013],{},[22,16143,16144],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,16145,16146,16156,16162],{"__ignoreMap":28},[70,16147,16148,16150,16152,16154],{"class":72,"line":73},[70,16149,52],{"class":76},[70,16151,125],{"class":124},[70,16153,125],{"class":124},[70,16155,130],{"class":124},[70,16157,16158,16160],{"class":72,"line":133},[70,16159,136],{"class":80},[70,16161,130],{"class":124},[70,16163,16164],{"class":72,"line":141},[70,16165,144],{"class":80},[15,16167,13340],{},[22,16169,16170],{"className":64,"code":963,"language":66,"meta":28,"style":28},[30,16171,16172],{"__ignoreMap":28},[70,16173,16174,16176],{"class":72,"line":73},[70,16175,970],{"class":76},[70,16177,973],{"class":80},[15,16179,16180],{},"也可以看十六进制：",[22,16182,16184],{"className":64,"code":16183,"language":66,"meta":28,"style":28},"xxd -g 1 \u002Fdev\u002Fpts\u002F4\n# 或者\ncat \u002Fdev\u002Fpts\u002F4 | xxd -g 1\n",[30,16185,16186,16198,16203],{"__ignoreMap":28},[70,16187,16188,16191,16194,16196],{"class":72,"line":73},[70,16189,16190],{"class":76},"xxd",[70,16192,16193],{"class":124}," -g",[70,16195,515],{"class":124},[70,16197,973],{"class":80},[70,16199,16200],{"class":72,"line":133},[70,16201,16202],{"class":295},"# 或者\n",[70,16204,16205,16207,16210,16213,16216,16218],{"class":72,"line":141},[70,16206,970],{"class":76},[70,16208,16209],{"class":80}," \u002Fdev\u002Fpts\u002F4",[70,16211,16212],{"class":219}," |",[70,16214,16215],{"class":76}," xxd",[70,16217,16193],{"class":124},[70,16219,16220],{"class":124}," 1\n",[15,16222,16223],{},"运行程序。",[15,16225,16226],{},"如果要测试程序接收数据，可以再打开一个终端：",[22,16228,16229],{"className":64,"code":13362,"language":66,"meta":28,"style":28},[30,16230,16231],{"__ignoreMap":28},[70,16232,16233,16235,16237,16239],{"class":72,"line":73},[70,16234,10778],{"class":124},[70,16236,10781],{"class":80},[70,16238,1976],{"class":219},[70,16240,973],{"class":80},[15,16242,16243],{},[995,16244],{"alt":28,"src":16245},"https:\u002F\u002Fcdn.tungchiahui.cn\u002Ftungwebsite\u002Fassets\u002Fimages\u002F2023\u002F10\u002F05\u002F1789479911824-caae3025.webp",[55,16247,16248],{"id":16248},"整个线程关系",[15,16250,16251],{},"现在程序里已经有两个线程：",[22,16253,16256],{"className":16254,"code":16255,"language":27,"meta":28},[25],"主线程\n\nAsio线程\n",[30,16257,16255],{"__ignoreMap":28},[15,16259,16260],{},"主线程：",[22,16262,16265],{"className":16263,"code":16264,"language":27,"meta":28},[25],"main()\n↓\n产生数据\n↓\nserial.async_send()\n↓\n继续做其他工作\n",[30,16266,16264],{"__ignoreMap":28},[15,16268,16269],{},"Asio 线程：",[22,16271,16274],{"className":16272,"code":16273,"language":27,"meta":28},[25],"io.run()\n↓\n执行串口相关 handler\n↓\n读串口\n↓\n写串口\n↓\n维护 write_queue_\n",[30,16275,16273],{"__ignoreMap":28},[15,16277,16278],{},"可以画成：",[22,16280,16283],{"className":16281,"code":16282,"language":27,"meta":28},[25],"主线程\n│\n├── async_send(\"message one\")\n│\n├── async_send(\"message two\")\n│\n└── async_send(\"message three\")\n        │\n        │ post()\n        ↓\n================================\n             Asio线程\n================================\n        │\n        ↓\n   enqueue_write()\n        ↓\n    write_queue_\n        ↓\n     do_write()\n        ↓\n   async_write()\n",[30,16284,16282],{"__ignoreMap":28},[15,16286,2160],{},[12,16288,16289],{},[15,16290,16291,16293],{},[30,16292,9089],{}," 并不意味着 main 线程亲自操作串口。",[15,16295,16296],{},"它只是把任务交给：",[22,16298,16301],{"className":16299,"code":16300,"language":27,"meta":28},[25],"Asio线程\n",[30,16302,16300],{"__ignoreMap":28},[15,16304,16305],{},"去执行。",[40,16307],{},[55,16309,16311,16312,11288],{"id":16310},"为什么要使用-post","为什么要使用 ",[30,16313,16314],{},"post()",[15,16316,16317],{},"这是本示例非常重要的一点。",[15,16319,16320],{},"假设我们不使用：",[22,16322,16324],{"className":210,"code":16323,"language":212,"meta":28,"style":28},"boost::asio::post(...)\n",[30,16325,16326],{"__ignoreMap":28},[70,16327,16328,16330,16332,16334,16336,16338],{"class":72,"line":73},[70,16329,540],{"class":76},[70,16331,386],{"class":264},[70,16333,389],{"class":76},[70,16335,386],{"class":264},[70,16337,14251],{"class":76},[70,16339,3449],{"class":264},[15,16341,16342],{},"而是让：",[22,16344,16346],{"className":210,"code":16345,"language":212,"meta":28,"style":28},"async_send()\n",[30,16347,16348],{"__ignoreMap":28},[70,16349,16350,16352],{"class":72,"line":73},[70,16351,7685],{"class":76},[70,16353,3162],{"class":264},[15,16355,16356],{},"直接执行：",[22,16358,16359],{"className":210,"code":9178,"language":212,"meta":28,"style":28},[30,16360,16361],{"__ignoreMap":28},[70,16362,16363,16365,16367],{"class":72,"line":73},[70,16364,8272],{"class":264},[70,16366,8299],{"class":76},[70,16368,8302],{"class":264},[15,16370,16371],{},"就会出现：",[22,16373,16376],{"className":16374,"code":16375,"language":27,"meta":28},[25],"main线程\n↓\nwrite_queue_.push_back()\n\n          同时\n\nAsio线程\n↓\nwrite_queue_.pop_front()\n",[30,16377,16375],{"__ignoreMap":28},[15,16379,16380],{},"也就是两个线程同时操作：",[22,16382,16383],{"className":210,"code":13560,"language":212,"meta":28,"style":28},[30,16384,16385],{"__ignoreMap":28},[70,16386,16387],{"class":72,"line":73},[70,16388,13560],{"class":264},[15,16390,16391],{},"这会产生：",[22,16393,16396],{"className":16394,"code":16395,"language":27,"meta":28},[25],"data race\n",[30,16397,16395],{"__ignoreMap":28},[40,16399],{},[55,16401,16403,16404,16407,16408],{"id":16402},"如果直接共享-write_queue_就需要-mutex","如果直接共享 ",[30,16405,16406],{},"write_queue_","，就需要 ",[30,16409,13542],{},[15,16411,16412],{},"传统解决办法是：",[22,16414,16416],{"className":210,"code":16415,"language":212,"meta":28,"style":28},"std::mutex mutex_;\n",[30,16417,16418],{"__ignoreMap":28},[70,16419,16420,16422],{"class":72,"line":73},[70,16421,2058],{"class":76},[70,16423,16424],{"class":264},"::mutex mutex_;\n",[15,16426,16427],{},"然后 main 线程修改队列：",[22,16429,16431],{"className":210,"code":16430,"language":212,"meta":28,"style":28},"{\n    std::scoped_lock lock(mutex_);\n\n    write_queue_.push_back(msg);\n}\n",[30,16432,16433,16437,16450,16454,16463],{"__ignoreMap":28},[70,16434,16435],{"class":72,"line":73},[70,16436,289],{"class":264},[70,16438,16439,16441,16444,16447],{"class":72,"line":133},[70,16440,302],{"class":76},[70,16442,16443],{"class":264},"::scoped_lock ",[70,16445,16446],{"class":76},"lock",[70,16448,16449],{"class":264},"(mutex_);\n",[70,16451,16452],{"class":72,"line":141},[70,16453,252],{"emptyLinePlaceholder":251},[70,16455,16456,16459,16461],{"class":72,"line":240},[70,16457,16458],{"class":264},"    write_queue_.",[70,16460,8299],{"class":76},[70,16462,8302],{"class":264},[70,16464,16465],{"class":72,"line":248},[70,16466,920],{"class":264},[15,16468,16469],{},"Asio 线程删除队首：",[22,16471,16473],{"className":210,"code":16472,"language":212,"meta":28,"style":28},"{\n    std::scoped_lock lock(mutex_);\n\n    write_queue_.pop_front();\n}\n",[30,16474,16475,16479,16489,16493,16501],{"__ignoreMap":28},[70,16476,16477],{"class":72,"line":73},[70,16478,289],{"class":264},[70,16480,16481,16483,16485,16487],{"class":72,"line":133},[70,16482,302],{"class":76},[70,16484,16443],{"class":264},[70,16486,16446],{"class":76},[70,16488,16449],{"class":264},[70,16490,16491],{"class":72,"line":141},[70,16492,252],{"emptyLinePlaceholder":251},[70,16494,16495,16497,16499],{"class":72,"line":240},[70,16496,16458],{"class":264},[70,16498,8645],{"class":76},[70,16500,2240],{"class":264},[70,16502,16503],{"class":72,"line":248},[70,16504,920],{"class":264},[15,16506,16507],{},"于是：",[22,16509,16512],{"className":16510,"code":16511,"language":27,"meta":28},[25],"main线程 ─────┐\n              │\n              ↓\n            mutex\n              ↓\n         write_queue_\n              ↑\n              │\nAsio线程 ─────┘\n",[30,16513,16511],{"__ignoreMap":28},[15,16515,16516],{},"这样同一时刻只有一个线程能访问队列。",[15,16518,16519],{},"这就是：",[22,16521,16523],{"className":210,"code":16522,"language":212,"meta":28,"style":28},"mutex\n",[30,16524,16525],{"__ignoreMap":28},[70,16526,16527],{"class":72,"line":73},[70,16528,16522],{"class":264},[15,16530,16531],{},"最典型的用途：",[12,16533,16534],{},[15,16535,16536],{},"多个线程必须直接访问同一个共享可变数据时，用锁保护临界区。",[40,16538],{},[55,16540,16542,16543,11288],{"id":16541},"但本例为什么没有使用-mutex","但本例为什么没有使用 ",[30,16544,13542],{},[15,16546,16547],{},"因为我们改变了设计。",[15,16549,16550],{},"main 线程不再直接碰：",[22,16552,16553],{"className":210,"code":13560,"language":212,"meta":28,"style":28},[30,16554,16555],{"__ignoreMap":28},[70,16556,16557],{"class":72,"line":73},[70,16558,13560],{"class":264},[15,16560,16561],{},"main 线程只执行：",[22,16563,16564],{"className":210,"code":16323,"language":212,"meta":28,"style":28},[30,16565,16566],{"__ignoreMap":28},[70,16567,16568,16570,16572,16574,16576,16578],{"class":72,"line":73},[70,16569,540],{"class":76},[70,16571,386],{"class":264},[70,16573,389],{"class":76},[70,16575,386],{"class":264},[70,16577,14251],{"class":76},[70,16579,3449],{"class":264},[15,16581,16582],{},"真正的：",[22,16584,16586],{"className":210,"code":16585,"language":212,"meta":28,"style":28},"write_queue_.push_back()\n",[30,16587,16588],{"__ignoreMap":28},[70,16589,16590,16592,16594],{"class":72,"line":73},[70,16591,8272],{"class":264},[70,16593,8299],{"class":76},[70,16595,3162],{"class":264},[15,16597,16598],{},"发生在：",[22,16600,16602],{"className":210,"code":16601,"language":212,"meta":28,"style":28},"enqueue_write()\n",[30,16603,16604],{"__ignoreMap":28},[70,16605,16606,16609],{"class":72,"line":73},[70,16607,16608],{"class":76},"enqueue_write",[70,16610,3162],{"class":264},[15,16612,16613],{},"里面。",[15,16615,16616,16617,16620],{},"而 ",[30,16618,16619],{},"enqueue_write()"," 是由：",[22,16622,16625],{"className":16623,"code":16624,"language":27,"meta":28},[25],"唯一的 Asio线程\n",[30,16626,16624],{"__ignoreMap":28},[15,16628,16629],{},"执行的。",[15,16631,16632],{},"同时：",[22,16634,16636],{"className":210,"code":16635,"language":212,"meta":28,"style":28},"on_write()\n",[30,16637,16638],{"__ignoreMap":28},[70,16639,16640,16642],{"class":72,"line":73},[70,16641,9344],{"class":76},[70,16643,3162],{"class":264},[15,16645,16646],{},"也是这个 Asio 线程执行。",[15,16648,2160],{},[22,16650,16653],{"className":16651,"code":16652,"language":27,"meta":28},[25],"main线程\n↓\n只 post()\n↓\n不访问 write_queue_\n\n\nAsio线程\n↓\npush_back()\npop_front()\nfront()\n↓\n所有队列操作都由同一个线程完成\n",[30,16654,16652],{"__ignoreMap":28},[15,16656,3182],{},[22,16658,16661],{"className":16659,"code":16660,"language":27,"meta":28},[25],"没有两个线程同时访问 write_queue_\n",[30,16662,16660],{"__ignoreMap":28},[15,16664,16665],{},"自然也就不需要：",[22,16667,16668],{"className":210,"code":16522,"language":212,"meta":28,"style":28},[30,16669,16670],{"__ignoreMap":28},[70,16671,16672],{"class":72,"line":73},[70,16673,16522],{"class":264},[15,16675,16676],{},"这是一个非常重要的并发设计思想：",[12,16678,16679],{},[15,16680,16681],{},"能通过“让某个状态只属于一个线程”解决的问题，就不一定非要让多个线程共享它再到处加锁。",[40,16683],{},[55,16685,16687,16689],{"id":16686},"post-可以理解成什么",[30,16688,16314],{}," 可以理解成什么？",[15,16691,2746],{},[22,16693,16695],{"className":210,"code":16694,"language":212,"meta":28,"style":28},"serial.async_send(\"message one\\n\");\n",[30,16696,16697],{"__ignoreMap":28},[70,16698,16699,16701,16703,16705,16707,16709,16711],{"class":72,"line":73},[70,16700,3970],{"class":264},[70,16702,7685],{"class":76},[70,16704,265],{"class":264},[70,16706,7690],{"class":80},[70,16708,753],{"class":124},[70,16710,756],{"class":80},[70,16712,898],{"class":264},[15,16714,16715],{},"内部：",[22,16717,16719],{"className":210,"code":16718,"language":212,"meta":28,"style":28},"boost::asio::post(\n    io_,\n    std::bind(\n        &AsyncSerialPort::enqueue_write,\n        this,\n        msg));\n",[30,16720,16721,16735,16740,16750,16759,16766],{"__ignoreMap":28},[70,16722,16723,16725,16727,16729,16731,16733],{"class":72,"line":73},[70,16724,540],{"class":76},[70,16726,386],{"class":264},[70,16728,389],{"class":76},[70,16730,386],{"class":264},[70,16732,14251],{"class":76},[70,16734,620],{"class":264},[70,16736,16737],{"class":72,"line":133},[70,16738,16739],{"class":264},"    io_,\n",[70,16741,16742,16744,16746,16748],{"class":72,"line":141},[70,16743,302],{"class":76},[70,16745,386],{"class":264},[70,16747,5144],{"class":76},[70,16749,620],{"class":264},[70,16751,16752,16755,16757],{"class":72,"line":240},[70,16753,16754],{"class":219},"        &",[70,16756,12464],{"class":76},[70,16758,14364],{"class":264},[70,16760,16761,16764],{"class":72,"line":248},[70,16762,16763],{"class":124},"        this",[70,16765,4555],{"class":264},[70,16767,16768],{"class":72,"line":255},[70,16769,16770],{"class":264},"        msg));\n",[15,16772,2874],{},[22,16774,16777],{"className":16775,"code":16776,"language":27,"meta":28},[25],"main线程：\n\n“这里有一个任务，\n以后请 io_context 帮我执行。”\n↓\npost()\n↓\n立即返回\n",[30,16778,16776],{"__ignoreMap":28},[15,16780,5727],{},[22,16782,16785],{"className":16783,"code":16784,"language":27,"meta":28},[25],"Asio线程：\n\nio.run()\n↓\n发现一个 post 过来的任务\n↓\n执行 enqueue_write()\n",[30,16786,16784],{"__ignoreMap":28},[15,16788,2160],{},[22,16790,16792],{"className":210,"code":16791,"language":212,"meta":28,"style":28},"post()\n",[30,16793,16794],{"__ignoreMap":28},[70,16795,16796,16798],{"class":72,"line":73},[70,16797,14251],{"class":76},[70,16799,3162],{"class":264},[15,16801,16802],{},"非常适合：",[22,16804,16807],{"className":16805,"code":16806,"language":27,"meta":28},[25],"其他线程\n↓\n向 Asio 线程提交任务\n",[30,16808,16806],{"__ignoreMap":28},[40,16810],{},[55,16812,16814,16817],{"id":16813},"work_guard-在这里为什么特别重要",[30,16815,16816],{},"work_guard"," 在这里为什么特别重要？",[15,16819,16820],{},"程序首先：",[22,16822,16824],{"className":210,"code":16823,"language":212,"meta":28,"style":28},"auto guard =\n    boost::asio::make_work_guard(io);\n",[30,16825,16826,16835],{"__ignoreMap":28},[70,16827,16828,16831,16833],{"class":72,"line":73},[70,16829,16830],{"class":219},"auto",[70,16832,15751],{"class":264},[70,16834,1689],{"class":219},[70,16836,16837,16839,16841,16843,16845,16847],{"class":72,"line":133},[70,16838,383],{"class":76},[70,16840,386],{"class":264},[70,16842,389],{"class":76},[70,16844,386],{"class":264},[70,16846,15767],{"class":76},[70,16848,416],{"class":264},[15,16850,16851],{},"然后启动：",[22,16853,16855],{"className":210,"code":16854,"language":212,"meta":28,"style":28},"std::thread io_thread(\n    std::bind(\n        run_io,\n        &io));\n",[30,16856,16857,16871,16881,16886],{"__ignoreMap":28},[70,16858,16859,16861,16863,16866,16869],{"class":72,"line":73},[70,16860,2058],{"class":76},[70,16862,386],{"class":264},[70,16864,16865],{"class":76},"thread",[70,16867,16868],{"class":76}," io_thread",[70,16870,620],{"class":264},[70,16872,16873,16875,16877,16879],{"class":72,"line":133},[70,16874,302],{"class":76},[70,16876,386],{"class":264},[70,16878,5144],{"class":76},[70,16880,620],{"class":264},[70,16882,16883],{"class":72,"line":141},[70,16884,16885],{"class":264},"        run_io,\n",[70,16887,16888,16890],{"class":72,"line":240},[70,16889,16754],{"class":219},[70,16891,15832],{"class":264},[15,16893,16894],{},"此时存在一种可能：",[22,16896,16899],{"className":16897,"code":16898,"language":27,"meta":28},[25],"Asio线程启动得非常快\n↓\n进入 io.run()\n↓\nserial.start() 还没来得及 post\n↓\n当前没有任务\n",[30,16900,16898],{"__ignoreMap":28},[15,16902,16903],{},"如果没有：",[22,16905,16907],{"className":210,"code":16906,"language":212,"meta":28,"style":28},"work_guard\n",[30,16908,16909],{"__ignoreMap":28},[70,16910,16911],{"class":72,"line":73},[70,16912,16906],{"class":264},[15,16914,11261],{},[22,16916,16919],{"className":16917,"code":16918,"language":27,"meta":28},[25],"io.run()\n↓\n发现没有工作\n↓\n直接返回\n↓\nAsio线程结束\n",[30,16920,16918],{"__ignoreMap":28},[15,16922,16923],{},"随后 main 再：",[22,16925,16927],{"className":210,"code":16926,"language":212,"meta":28,"style":28},"serial.start();\nserial.async_send(...);\n",[30,16928,16929,16937],{"__ignoreMap":28},[70,16930,16931,16933,16935],{"class":72,"line":73},[70,16932,3970],{"class":264},[70,16934,15857],{"class":76},[70,16936,2240],{"class":264},[70,16938,16939,16941,16943],{"class":72,"line":133},[70,16940,3970],{"class":264},[70,16942,7685],{"class":76},[70,16944,16945],{"class":264},"(...);\n",[15,16947,16948],{},"虽然任务被投递进：",[22,16950,16953],{"className":16951,"code":16952,"language":27,"meta":28},[25],"io_context\n",[30,16954,16952],{"__ignoreMap":28},[15,16956,16957],{},"但是已经没有线程执行：",[22,16959,16961],{"className":210,"code":16960,"language":212,"meta":28,"style":28},"io.run()\n",[30,16962,16963],{"__ignoreMap":28},[70,16964,16965,16967,16969],{"class":72,"line":73},[70,16966,2234],{"class":264},[70,16968,2237],{"class":76},[70,16970,3162],{"class":264},[15,16972,16973],{},"任务就不会被处理。",[15,16975,16976],{},"有了：",[22,16978,16979],{"className":210,"code":16906,"language":212,"meta":28,"style":28},[30,16980,16981],{"__ignoreMap":28},[70,16982,16983],{"class":72,"line":73},[70,16984,16906],{"class":264},[15,16986,16987],{},"流程变成：",[22,16989,16992],{"className":16990,"code":16991,"language":27,"meta":28},[25],"Asio线程\n↓\nio.run()\n↓\n暂时没有任务\n↓\n但 guard 还在\n↓\n不能退出\n↓\n继续等待\n↓\nmain post 新任务\n↓\n开始执行\n",[30,16993,16991],{"__ignoreMap":28},[15,16995,16996],{},"所以这里：",[22,16998,16999],{"className":210,"code":16906,"language":212,"meta":28,"style":28},[30,17000,17001],{"__ignoreMap":28},[70,17002,17003],{"class":72,"line":73},[70,17004,16906],{"class":264},[15,17006,17007],{},"真正体现出了：",[12,17009,17010],{},[15,17011,17012],{},"后台 Asio 线程暂时没任务时也不要退出，后面其他线程还可能继续投递任务。",[40,17014],{},[55,17016,17018,17019,17022,17023,11288],{"id":17017},"为什么结束时先-stop再-guardreset","为什么结束时先 ",[30,17020,17021],{},"stop()","，再 ",[30,17024,17025],{},"guard.reset()",[15,17027,17028],{},"程序退出时：",[22,17030,17032],{"className":210,"code":17031,"language":212,"meta":28,"style":28},"serial.stop();\n\nguard.reset();\n\nio_thread.join();\n",[30,17033,17034,17042,17046,17055,17059],{"__ignoreMap":28},[70,17035,17036,17038,17040],{"class":72,"line":73},[70,17037,3970],{"class":264},[70,17039,16057],{"class":76},[70,17041,2240],{"class":264},[70,17043,17044],{"class":72,"line":133},[70,17045,252],{"emptyLinePlaceholder":251},[70,17047,17048,17051,17053],{"class":72,"line":141},[70,17049,17050],{"class":264},"guard.",[70,17052,16079],{"class":76},[70,17054,2240],{"class":264},[70,17056,17057],{"class":72,"line":240},[70,17058,252],{"emptyLinePlaceholder":251},[70,17060,17061,17064,17066],{"class":72,"line":248},[70,17062,17063],{"class":264},"io_thread.",[70,17065,16095],{"class":76},[70,17067,2240],{"class":264},[15,17069,3047],{},[22,17071,17073],{"className":210,"code":17072,"language":212,"meta":28,"style":28},"serial.stop();\n",[30,17074,17075],{"__ignoreMap":28},[70,17076,17077,17079,17081],{"class":72,"line":73},[70,17078,3970],{"class":264},[70,17080,16057],{"class":76},[70,17082,2240],{"class":264},[15,17084,17085],{},"并不是直接由 main 线程关闭串口。",[15,17087,17088],{},"它内部：",[22,17090,17092],{"className":210,"code":17091,"language":212,"meta":28,"style":28},"post(...)\n",[30,17093,17094],{"__ignoreMap":28},[70,17095,17096,17098],{"class":72,"line":73},[70,17097,14251],{"class":76},[70,17099,3449],{"class":264},[15,17101,17102],{},"把：",[22,17104,17107],{"className":17105,"code":17106,"language":27,"meta":28},[25],"关闭串口\n",[30,17108,17106],{"__ignoreMap":28},[15,17110,17111],{},"这个任务交给 Asio 线程。",[15,17113,5727],{},[22,17115,17117],{"className":210,"code":17116,"language":212,"meta":28,"style":28},"guard.reset();\n",[30,17118,17119],{"__ignoreMap":28},[70,17120,17121,17123,17125],{"class":72,"line":73},[70,17122,17050],{"class":264},[70,17124,16079],{"class":76},[70,17126,2240],{"class":264},[15,17128,2203],{},[12,17130,17131],{},[15,17132,17133,17134,17136],{},"不再人为保持 ",[30,17135,7273],{}," 存活。",[15,17138,17139],{},"Asio 线程处理完：",[22,17141,17144],{"className":17142,"code":17143,"language":27,"meta":28},[25],"关闭串口\n取消异步读取\n处理剩余 handler\n",[30,17145,17143],{"__ignoreMap":28},[15,17147,17148],{},"以后，如果没有其他工作：",[22,17150,17153],{"className":17151,"code":17152,"language":27,"meta":28},[25],"io.run()\n↓\n返回\n",[30,17154,17152],{"__ignoreMap":28},[15,17156,17157],{},"最后：",[22,17159,17161],{"className":210,"code":17160,"language":212,"meta":28,"style":28},"io_thread.join();\n",[30,17162,17163],{"__ignoreMap":28},[70,17164,17165,17167,17169],{"class":72,"line":73},[70,17166,17063],{"class":264},[70,17168,16095],{"class":76},[70,17170,2240],{"class":264},[15,17172,17173],{},"等待 Asio 线程真正结束。",[15,17175,17176],{},"所以退出流程：",[22,17178,17181],{"className":17179,"code":17180,"language":27,"meta":28},[25],"main\n↓\npost(stop)\n↓\nguard.reset()\n↓\n等待 join()\n\n\nAsio线程\n↓\n处理 stop\n↓\n取消串口异步任务\n↓\n没有其他工作\n↓\nio.run() 返回\n↓\n线程结束\n",[30,17182,17180],{"__ignoreMap":28},[40,17184],{},[55,17186,17188],{"id":17187},"示例-8-最重要的架构","示例 8 最重要的架构",[15,17190,3931],{},[22,17192,17195],{"className":17193,"code":17194,"language":27,"meta":28},[25],"业务线程 \u002F main线程\n        │\n        │ async_send()\n        ↓\n      post()\n        │\n        ↓\n==============================\n       Asio通信线程\n==============================\n        │\n        ├── serial_port\n        ├── read_buffer_\n        ├── write_queue_\n        ├── async_read()\n        └── async_write()\n",[30,17196,17194],{"__ignoreMap":28},[15,17198,13753],{},[22,17200,17203],{"className":17201,"code":17202,"language":27,"meta":28},[25],"业务逻辑\n",[30,17204,17202],{"__ignoreMap":28},[15,17206,3277],{},[22,17208,17211],{"className":17209,"code":17210,"language":27,"meta":28},[25],"串口 I\u002FO\n",[30,17212,17210],{"__ignoreMap":28},[15,17214,17215],{},"就被放到了不同线程。",[15,17217,17218],{},"同时利用：",[22,17220,17221],{"className":210,"code":16791,"language":212,"meta":28,"style":28},[30,17222,17223],{"__ignoreMap":28},[70,17224,17225,17227],{"class":72,"line":73},[70,17226,14251],{"class":76},[70,17228,3162],{"class":264},[15,17230,17231],{},"避免 main 线程和 Asio 线程直接共同修改串口内部状态。",[15,17233,3227],{},[12,17235,17236],{},[15,17237,17238,17239,17241,17242,17244],{},"一个独立 Asio 通信线程时，可以让其他线程只通过 ",[30,17240,16314],{}," 提交任务，而把串口、buffer、发送队列等内部状态全部交给 Asio 线程管理，从而减少对 ",[30,17243,13542],{}," 的需求。",[40,17246],{},[43,17248,17250,17251,17253,17254,17257],{"id":17249},"示例-9多个线程同时运行-iorun使用-strand-避免-handler-并发","示例 9：多个线程同时运行 ",[30,17252,7273],{},"，使用 ",[30,17255,17256],{},"strand"," 避免 handler 并发",[15,17259,17260],{},"这种情况一般适用于多个通信设备。（此时main有1个主线程，asio有2+个线程）",[55,17262,186],{"id":17263},"程序目标-8",[15,17265,17266],{},"示例 8 中只有：",[22,17268,17271],{"className":17269,"code":17270,"language":27,"meta":28},[25],"一个 Asio线程\n",[30,17272,17270],{"__ignoreMap":28},[15,17274,17275],{},"执行：",[22,17277,17278],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,17279,17280],{"__ignoreMap":28},[70,17281,17282,17284,17286],{"class":72,"line":73},[70,17283,2234],{"class":264},[70,17285,2237],{"class":76},[70,17287,2240],{"class":264},[15,17289,3182],{},[22,17291,17294],{"className":17292,"code":17293,"language":27,"meta":28},[25],"enqueue_write()\non_write()\non_read()\n",[30,17295,17293],{"__ignoreMap":28},[15,17297,17298],{},"这些 handler 本身不会同时执行。",[15,17300,17301],{},"但是如果我们为了让：",[22,17303,17304],{"className":210,"code":16952,"language":212,"meta":28,"style":28},[30,17305,17306],{"__ignoreMap":28},[70,17307,17308],{"class":72,"line":73},[70,17309,16952],{"class":264},[15,17311,17312],{},"拥有更强的并发处理能力，改成：",[22,17314,17317],{"className":17315,"code":17316,"language":27,"meta":28},[25],"Asio线程1 → io.run()\n\nAsio线程2 → io.run()\n",[30,17318,17316],{"__ignoreMap":28},[15,17320,11261],{},[22,17322,17325],{"className":17323,"code":17324,"language":27,"meta":28},[25],"不同 handler\n",[30,17326,17324],{"__ignoreMap":28},[15,17328,17329],{},"就可能在两个线程上同时执行。",[15,17331,2746],{},[22,17333,17336],{"className":17334,"code":17335,"language":27,"meta":28},[25],"Asio线程1\n↓\nenqueue_write()\n↓\nwrite_queue_.push_back()\n\n\nAsio线程2\n↓\non_write()\n↓\nwrite_queue_.pop_front()\n",[30,17337,17335],{"__ignoreMap":28},[15,17339,17340],{},"如果同时发生，就又产生了数据竞争。",[15,17342,17343],{},"这一节使用：",[22,17345,17346],{"className":210,"code":13648,"language":212,"meta":28,"style":28},[30,17347,17348],{"__ignoreMap":28},[70,17349,17350],{"class":72,"line":73},[70,17351,13648],{"class":264},[15,17353,17354],{},"解决这个问题。",[15,17356,17357],{},"核心规则：",[12,17359,17360],{},[15,17361,17362,17363,17365],{},"绑定到同一个 ",[30,17364,17256],{}," 的 handler 不会彼此并发执行。",[55,17367,207],{"id":17368},"完整代码-8",[22,17370,17372],{"className":210,"code":17371,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n#include \u003Cboost\u002Fsystem\u002Ferror_code.hpp>\n#include \u003Carray>\n#include \u003Cdeque>\n#include \u003Cfunctional>\n#include \u003Ciostream>\n#include \u003Cprint>\n#include \u003Cstring>\n#include \u003Cthread>\n\nclass AsyncSerialPort\n{\npublic:\n    AsyncSerialPort(\n        boost::asio::io_context& io,\n        const std::string& port_name)\n        : strand_(boost::asio::make_strand(io)),\n          serial_(io)\n    {\n        boost::system::error_code ec;\n\n        serial_.open(port_name, ec);\n\n        if (ec)\n        {\n            std::println(\n                \"打开串口失败：{}\",\n                ec.message());\n\n            return;\n        }\n\n        serial_.set_option(\n            boost::asio::serial_port_base::baud_rate(115200));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::character_size(8));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::parity(\n                boost::asio::serial_port_base::parity::none));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::stop_bits(\n                boost::asio::serial_port_base::stop_bits::one));\n\n        serial_.set_option(\n            boost::asio::serial_port_base::flow_control(\n                boost::asio::serial_port_base::flow_control::none));\n\n        std::println(\n            \"AsyncSerialPort：串口打开成功\");\n    }\n\n    void start()\n    {\n        \u002F\u002F start_read() 也通过 strand 执行。\n        boost::asio::post(\n            strand_,\n            std::bind(\n                &AsyncSerialPort::start_read,\n                this));\n    }\n\n    void async_send(const std::string& msg)\n    {\n        \u002F\u002F 所有修改发送队列的任务，\n        \u002F\u002F 都先投递到同一个 strand。\n        boost::asio::post(\n            strand_,\n            std::bind(\n                &AsyncSerialPort::enqueue_write,\n                this,\n                msg));\n    }\n\n    void stop()\n    {\n        boost::asio::post(\n            strand_,\n            std::bind(\n                &AsyncSerialPort::do_stop,\n                this));\n    }\n\nprivate:\n    void start_read()\n    {\n        if (stopping_ || !serial_.is_open())\n        {\n            return;\n        }\n\n        boost::asio::async_read(\n            serial_,\n            boost::asio::buffer(read_buffer_),\n\n            \u002F\u002F 读取完成的 handler 也绑定到同一个 strand。\n            boost::asio::bind_executor(\n                strand_,\n                std::bind(\n                    &AsyncSerialPort::on_read,\n                    this,\n                    std::placeholders::_1,\n                    std::placeholders::_2)));\n    }\n\n    void on_read(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"读取结束：{}，线程 id = {}\",\n                ec.message(),\n                std::this_thread::get_id());\n\n            return;\n        }\n\n        std::string msg(\n            read_buffer_.data(),\n            bytes_transferred);\n\n        std::println(\n            \"收到数据，bytes = {}，线程 id = {}，内容 = {}\",\n            bytes_transferred,\n            std::this_thread::get_id(),\n            msg);\n\n        if (!stopping_)\n        {\n            start_read();\n        }\n    }\n\n    void enqueue_write(std::string msg)\n    {\n        if (stopping_)\n        {\n            return;\n        }\n\n        std::println(\n            \"enqueue_write()，线程 id = {}\",\n            std::this_thread::get_id());\n\n        bool writing =\n            !write_queue_.empty();\n\n        write_queue_.push_back(msg);\n\n        if (!writing)\n        {\n            do_write();\n        }\n    }\n\n    void do_write()\n    {\n        if (stopping_ || write_queue_.empty())\n        {\n            return;\n        }\n\n        boost::asio::async_write(\n            serial_,\n            boost::asio::buffer(\n                write_queue_.front()),\n\n            \u002F\u002F 写完成 handler 同样绑定到 strand。\n            boost::asio::bind_executor(\n                strand_,\n                std::bind(\n                    &AsyncSerialPort::on_write,\n                    this,\n                    std::placeholders::_1,\n                    std::placeholders::_2)));\n    }\n\n    void on_write(\n        const boost::system::error_code& ec,\n        std::size_t bytes_transferred)\n    {\n        if (ec)\n        {\n            std::println(\n                \"发送结束：{}，线程 id = {}\",\n                ec.message(),\n                std::this_thread::get_id());\n\n            return;\n        }\n\n        std::println(\n            \"发送完成，bytes = {}，线程 id = {}\",\n            bytes_transferred,\n            std::this_thread::get_id());\n\n        write_queue_.pop_front();\n\n        if (!write_queue_.empty())\n        {\n            do_write();\n        }\n    }\n\n    void do_stop()\n    {\n        if (stopping_)\n        {\n            return;\n        }\n\n        stopping_ = true;\n\n        std::println(\n            \"关闭串口，线程 id = {}\",\n            std::this_thread::get_id());\n\n        boost::system::error_code ec;\n\n        serial_.cancel(ec);\n\n        ec.clear();\n\n        serial_.close(ec);\n    }\n\nprivate:\n    boost::asio::strand\u003C\n        boost::asio::io_context::executor_type>\n        strand_;\n\n    boost::asio::serial_port serial_;\n\n    std::array\u003Cchar, 11> read_buffer_{};\n\n    std::deque\u003Cstd::string> write_queue_;\n\n    bool stopping_ = false;\n};\n\nvoid run_io(\n    boost::asio::io_context* io,\n    const std::string& name)\n{\n    std::println(\n        \"{}：开始 io.run()，线程 id = {}\",\n        name,\n        std::this_thread::get_id());\n\n    io->run();\n\n    std::println(\n        \"{}：io.run() 返回\",\n        name);\n}\n\nint main(int argc, char* argv[])\n{\n    std::string port_name = \"\u002Fdev\u002Fpts\u002F3\";\n\n    if (argc >= 2)\n    {\n        port_name = argv[1];\n    }\n\n    boost::asio::io_context io;\n\n    auto guard =\n        boost::asio::make_work_guard(io);\n\n    AsyncSerialPort serial(io, port_name);\n\n    \u002F\u002F 两个线程同时运行同一个 io_context。\n    std::thread t1(\n        std::bind(\n            run_io,\n            &io,\n            std::string(\"Asio线程1\")));\n\n    std::thread t2(\n        std::bind(\n            run_io,\n            &io,\n            std::string(\"Asio线程2\")));\n\n    serial.start();\n\n    serial.async_send(\"message one\\n\");\n    serial.async_send(\"message two\\n\");\n    serial.async_send(\"message three\\n\");\n\n    std::println(\n        \"main：两个 Asio 线程正在运行，按 Enter 结束\");\n\n    std::string input;\n    std::getline(std::cin, input);\n\n    serial.stop();\n\n    guard.reset();\n\n    t1.join();\n    t2.join();\n\n    std::println(\"main：程序结束\");\n\n    return 0;\n}\n",[30,17373,17374,17380,17386,17392,17398,17404,17410,17416,17422,17428,17432,17438,17442,17446,17452,17470,17486,17509,17515,17519,17529,17533,17541,17545,17551,17555,17565,17571,17579,17583,17589,17593,17597,17605,17627,17631,17639,17661,17665,17673,17691,17709,17713,17721,17739,17757,17761,17769,17787,17805,17809,17819,17825,17829,17833,17841,17845,17850,17864,17869,17879,17887,17893,17897,17901,17923,17927,17932,17937,17951,17955,17965,17973,17979,17983,17987,17991,17999,18003,18017,18021,18031,18039,18045,18049,18053,18057,18065,18069,18085,18089,18095,18099,18103,18117,18121,18135,18139,18144,18159,18164,18174,18183,18190,18201,18212,18216,18220,18228,18248,18260,18264,18270,18274,18284,18291,18299,18313,18317,18323,18327,18331,18341,18349,18353,18357,18367,18374,18378,18392,18396,18400,18410,18414,18420,18424,18428,18432,18450,18454,18460,18464,18470,18474,18478,18488,18495,18509,18513,18521,18532,18536,18544,18548,18558,18562,18568,18572,18576,18580,18588,18592,18606,18610,18616,18620,18624,18638,18642,18656,18664,18668,18673,18687,18691,18701,18709,18715,18725,18735,18739,18743,18751,18771,18783,18787,18793,18797,18807,18814,18822,18836,18840,18846,18850,18854,18864,18871,18875,18889,18893,18901,18905,18919,18923,18929,18933,18937,18941,18949,18953,18959,18963,18969,18973,18977,18987,18991,19001,19008,19022,19026,19036,19040,19048,19052,19060,19064,19072,19076,19080,19084,19098,19116,19121,19125,19135,19139,19155,19159,19175,19179,19191,19195,19199,19207,19225,19242,19246,19256,19263,19268,19282,19286,19294,19298,19308,19315,19320,19324,19328,19348,19352,19364,19368,19380,19384,19396,19400,19404,19414,19418,19426,19440,19444,19452,19456,19461,19472,19482,19486,19493,19509,19513,19524,19534,19538,19544,19559,19563,19571,19575,19591,19607,19623,19627,19637,19644,19648,19654,19668,19672,19680,19684,19693,19698,19708,19718,19723,19738,19743,19752],{"__ignoreMap":28},[70,17375,17376,17378],{"class":72,"line":73},[70,17377,220],{"class":219},[70,17379,223],{"class":80},[70,17381,17382,17384],{"class":72,"line":133},[70,17383,220],{"class":219},[70,17385,230],{"class":80},[70,17387,17388,17390],{"class":72,"line":141},[70,17389,220],{"class":219},[70,17391,1172],{"class":80},[70,17393,17394,17396],{"class":72,"line":240},[70,17395,220],{"class":219},[70,17397,7797],{"class":80},[70,17399,17400,17402],{"class":72,"line":248},[70,17401,220],{"class":219},[70,17403,4504],{"class":80},[70,17405,17406,17408],{"class":72,"line":255},[70,17407,220],{"class":219},[70,17409,13803],{"class":80},[70,17411,17412,17414],{"class":72,"line":286},[70,17413,220],{"class":219},[70,17415,237],{"class":80},[70,17417,17418,17420],{"class":72,"line":292},[70,17419,220],{"class":219},[70,17421,245],{"class":80},[70,17423,17424,17426],{"class":72,"line":299},[70,17425,220],{"class":219},[70,17427,13822],{"class":80},[70,17429,17430],{"class":72,"line":317},[70,17431,252],{"emptyLinePlaceholder":251},[70,17433,17434,17436],{"class":72,"line":322},[70,17435,7824],{"class":219},[70,17437,11847],{"class":76},[70,17439,17440],{"class":72,"line":340},[70,17441,289],{"class":264},[70,17443,17444],{"class":72,"line":346},[70,17445,7836],{"class":219},[70,17447,17448,17450],{"class":72,"line":363},[70,17449,11860],{"class":76},[70,17451,620],{"class":264},[70,17453,17454,17456,17458,17460,17462,17464,17466,17468],{"class":72,"line":369},[70,17455,626],{"class":76},[70,17457,386],{"class":264},[70,17459,389],{"class":76},[70,17461,386],{"class":264},[70,17463,7856],{"class":76},[70,17465,4549],{"class":219},[70,17467,7861],{"class":270},[70,17469,4555],{"class":264},[70,17471,17472,17474,17476,17478,17480,17482,17484],{"class":72,"line":374},[70,17473,7868],{"class":219},[70,17475,7871],{"class":76},[70,17477,386],{"class":264},[70,17479,3196],{"class":76},[70,17481,4549],{"class":219},[70,17483,7880],{"class":270},[70,17485,337],{"class":264},[70,17487,17488,17490,17493,17495,17497,17499,17501,17503,17506],{"class":72,"line":380},[70,17489,7887],{"class":264},[70,17491,17492],{"class":76},"strand_",[70,17494,265],{"class":264},[70,17496,540],{"class":76},[70,17498,386],{"class":264},[70,17500,389],{"class":76},[70,17502,386],{"class":264},[70,17504,17505],{"class":76},"make_strand",[70,17507,17508],{"class":264},"(io)),\n",[70,17510,17511,17513],{"class":72,"line":395},[70,17512,13895],{"class":76},[70,17514,7893],{"class":264},[70,17516,17517],{"class":72,"line":401},[70,17518,343],{"class":264},[70,17520,17521,17523,17525,17527],{"class":72,"line":419},[70,17522,626],{"class":76},[70,17524,386],{"class":264},[70,17526,426],{"class":76},[70,17528,429],{"class":264},[70,17530,17531],{"class":72,"line":432},[70,17532,252],{"emptyLinePlaceholder":251},[70,17534,17535,17537,17539],{"class":72,"line":437},[70,17536,7916],{"class":264},[70,17538,466],{"class":76},[70,17540,469],{"class":264},[70,17542,17543],{"class":72,"line":455},[70,17544,252],{"emptyLinePlaceholder":251},[70,17546,17547,17549],{"class":72,"line":460},[70,17548,7929],{"class":219},[70,17550,477],{"class":264},[70,17552,17553],{"class":72,"line":472},[70,17554,7936],{"class":264},[70,17556,17557,17559,17561,17563],{"class":72,"line":480},[70,17558,5156],{"class":76},[70,17560,386],{"class":264},[70,17562,444],{"class":76},[70,17564,620],{"class":264},[70,17566,17567,17569],{"class":72,"line":485},[70,17568,7951],{"class":80},[70,17570,4555],{"class":264},[70,17572,17573,17575,17577],{"class":72,"line":509},[70,17574,7958],{"class":264},[70,17576,503],{"class":76},[70,17578,506],{"class":264},[70,17580,17581],{"class":72,"line":520},[70,17582,252],{"emptyLinePlaceholder":251},[70,17584,17585,17587],{"class":72,"line":525},[70,17586,7971],{"class":219},[70,17588,314],{"class":264},[70,17590,17591],{"class":72,"line":530},[70,17592,7978],{"class":264},[70,17594,17595],{"class":72,"line":565},[70,17596,252],{"emptyLinePlaceholder":251},[70,17598,17599,17601,17603],{"class":72,"line":596},[70,17600,7916],{"class":264},[70,17602,535],{"class":76},[70,17604,620],{"class":264},[70,17606,17607,17609,17611,17613,17615,17617,17619,17621,17623,17625],{"class":72,"line":623},[70,17608,1496],{"class":76},[70,17610,386],{"class":264},[70,17612,389],{"class":76},[70,17614,386],{"class":264},[70,17616,549],{"class":76},[70,17618,386],{"class":264},[70,17620,554],{"class":76},[70,17622,265],{"class":264},[70,17624,559],{"class":124},[70,17626,562],{"class":264},[70,17628,17629],{"class":72,"line":644},[70,17630,252],{"emptyLinePlaceholder":251},[70,17632,17633,17635,17637],{"class":72,"line":670},[70,17634,7916],{"class":264},[70,17636,535],{"class":76},[70,17638,620],{"class":264},[70,17640,17641,17643,17645,17647,17649,17651,17653,17655,17657,17659],{"class":72,"line":690},[70,17642,1496],{"class":76},[70,17644,386],{"class":264},[70,17646,389],{"class":76},[70,17648,386],{"class":264},[70,17650,549],{"class":76},[70,17652,386],{"class":264},[70,17654,586],{"class":76},[70,17656,265],{"class":264},[70,17658,591],{"class":124},[70,17660,562],{"class":264},[70,17662,17663],{"class":72,"line":716},[70,17664,252],{"emptyLinePlaceholder":251},[70,17666,17667,17669,17671],{"class":72,"line":735},[70,17668,7916],{"class":264},[70,17670,535],{"class":76},[70,17672,620],{"class":264},[70,17674,17675,17677,17679,17681,17683,17685,17687,17689],{"class":72,"line":740},[70,17676,1496],{"class":76},[70,17678,386],{"class":264},[70,17680,389],{"class":76},[70,17682,386],{"class":264},[70,17684,549],{"class":76},[70,17686,386],{"class":264},[70,17688,617],{"class":76},[70,17690,620],{"class":264},[70,17692,17693,17695,17697,17699,17701,17703,17705,17707],{"class":72,"line":761},[70,17694,8081],{"class":76},[70,17696,386],{"class":264},[70,17698,389],{"class":76},[70,17700,386],{"class":264},[70,17702,549],{"class":76},[70,17704,386],{"class":264},[70,17706,617],{"class":76},[70,17708,641],{"class":264},[70,17710,17711],{"class":72,"line":766},[70,17712,252],{"emptyLinePlaceholder":251},[70,17714,17715,17717,17719],{"class":72,"line":772},[70,17716,7916],{"class":264},[70,17718,535],{"class":76},[70,17720,620],{"class":264},[70,17722,17723,17725,17727,17729,17731,17733,17735,17737],{"class":72,"line":816},[70,17724,1496],{"class":76},[70,17726,386],{"class":264},[70,17728,389],{"class":76},[70,17730,386],{"class":264},[70,17732,549],{"class":76},[70,17734,386],{"class":264},[70,17736,665],{"class":76},[70,17738,620],{"class":264},[70,17740,17741,17743,17745,17747,17749,17751,17753,17755],{"class":72,"line":823},[70,17742,8081],{"class":76},[70,17744,386],{"class":264},[70,17746,389],{"class":76},[70,17748,386],{"class":264},[70,17750,549],{"class":76},[70,17752,386],{"class":264},[70,17754,665],{"class":76},[70,17756,687],{"class":264},[70,17758,17759],{"class":72,"line":828},[70,17760,252],{"emptyLinePlaceholder":251},[70,17762,17763,17765,17767],{"class":72,"line":848},[70,17764,7916],{"class":264},[70,17766,535],{"class":76},[70,17768,620],{"class":264},[70,17770,17771,17773,17775,17777,17779,17781,17783,17785],{"class":72,"line":857},[70,17772,1496],{"class":76},[70,17774,386],{"class":264},[70,17776,389],{"class":76},[70,17778,386],{"class":264},[70,17780,549],{"class":76},[70,17782,386],{"class":264},[70,17784,711],{"class":76},[70,17786,620],{"class":264},[70,17788,17789,17791,17793,17795,17797,17799,17801,17803],{"class":72,"line":862},[70,17790,8081],{"class":76},[70,17792,386],{"class":264},[70,17794,389],{"class":76},[70,17796,386],{"class":264},[70,17798,549],{"class":76},[70,17800,386],{"class":264},[70,17802,711],{"class":76},[70,17804,641],{"class":264},[70,17806,17807],{"class":72,"line":867},[70,17808,252],{"emptyLinePlaceholder":251},[70,17810,17811,17813,17815,17817],{"class":72,"line":884},[70,17812,488],{"class":76},[70,17814,386],{"class":264},[70,17816,444],{"class":76},[70,17818,620],{"class":264},[70,17820,17821,17823],{"class":72,"line":901},[70,17822,12213],{"class":80},[70,17824,898],{"class":264},[70,17826,17827],{"class":72,"line":906},[70,17828,366],{"class":264},[70,17830,17831],{"class":72,"line":917},[70,17832,252],{"emptyLinePlaceholder":251},[70,17834,17835,17837,17839],{"class":72,"line":1618},[70,17836,8223],{"class":219},[70,17838,14222],{"class":76},[70,17840,3162],{"class":264},[70,17842,17843],{"class":72,"line":1640},[70,17844,343],{"class":264},[70,17846,17847],{"class":72,"line":1645},[70,17848,17849],{"class":295},"        \u002F\u002F start_read() 也通过 strand 执行。\n",[70,17851,17852,17854,17856,17858,17860,17862],{"class":72,"line":1661},[70,17853,626],{"class":76},[70,17855,386],{"class":264},[70,17857,389],{"class":76},[70,17859,386],{"class":264},[70,17861,14251],{"class":76},[70,17863,620],{"class":264},[70,17865,17866],{"class":72,"line":1666},[70,17867,17868],{"class":264},"            strand_,\n",[70,17870,17871,17873,17875,17877],{"class":72,"line":1672},[70,17872,5156],{"class":76},[70,17874,386],{"class":264},[70,17876,5144],{"class":76},[70,17878,620],{"class":264},[70,17880,17881,17883,17885],{"class":72,"line":1678},[70,17882,8461],{"class":219},[70,17884,12464],{"class":76},[70,17886,14277],{"class":264},[70,17888,17889,17891],{"class":72,"line":1692},[70,17890,8472],{"class":124},[70,17892,562],{"class":264},[70,17894,17895],{"class":72,"line":1708},[70,17896,366],{"class":264},[70,17898,17899],{"class":72,"line":1714},[70,17900,252],{"emptyLinePlaceholder":251},[70,17902,17903,17905,17907,17909,17911,17913,17915,17917,17919,17921],{"class":72,"line":1730},[70,17904,8223],{"class":219},[70,17906,8226],{"class":76},[70,17908,265],{"class":264},[70,17910,5601],{"class":219},[70,17912,7871],{"class":76},[70,17914,386],{"class":264},[70,17916,3196],{"class":76},[70,17918,4549],{"class":219},[70,17920,3199],{"class":270},[70,17922,337],{"class":264},[70,17924,17925],{"class":72,"line":1736},[70,17926,343],{"class":264},[70,17928,17929],{"class":72,"line":1741},[70,17930,17931],{"class":295},"        \u002F\u002F 所有修改发送队列的任务，\n",[70,17933,17934],{"class":72,"line":1748},[70,17935,17936],{"class":295},"        \u002F\u002F 都先投递到同一个 strand。\n",[70,17938,17939,17941,17943,17945,17947,17949],{"class":72,"line":1753},[70,17940,626],{"class":76},[70,17942,386],{"class":264},[70,17944,389],{"class":76},[70,17946,386],{"class":264},[70,17948,14251],{"class":76},[70,17950,620],{"class":264},[70,17952,17953],{"class":72,"line":1773},[70,17954,17868],{"class":264},[70,17956,17957,17959,17961,17963],{"class":72,"line":1782},[70,17958,5156],{"class":76},[70,17960,386],{"class":264},[70,17962,5144],{"class":76},[70,17964,620],{"class":264},[70,17966,17967,17969,17971],{"class":72,"line":1787},[70,17968,8461],{"class":219},[70,17970,12464],{"class":76},[70,17972,14364],{"class":264},[70,17974,17975,17977],{"class":72,"line":1792},[70,17976,8472],{"class":124},[70,17978,4555],{"class":264},[70,17980,17981],{"class":72,"line":1798},[70,17982,14375],{"class":264},[70,17984,17985],{"class":72,"line":1818},[70,17986,366],{"class":264},[70,17988,17989],{"class":72,"line":1823},[70,17990,252],{"emptyLinePlaceholder":251},[70,17992,17993,17995,17997],{"class":72,"line":1839},[70,17994,8223],{"class":219},[70,17996,14390],{"class":76},[70,17998,3162],{"class":264},[70,18000,18001],{"class":72,"line":1856},[70,18002,343],{"class":264},[70,18004,18005,18007,18009,18011,18013,18015],{"class":72,"line":1861},[70,18006,626],{"class":76},[70,18008,386],{"class":264},[70,18010,389],{"class":76},[70,18012,386],{"class":264},[70,18014,14251],{"class":76},[70,18016,620],{"class":264},[70,18018,18019],{"class":72,"line":1876},[70,18020,17868],{"class":264},[70,18022,18023,18025,18027,18029],{"class":72,"line":1881},[70,18024,5156],{"class":76},[70,18026,386],{"class":264},[70,18028,5144],{"class":76},[70,18030,620],{"class":264},[70,18032,18033,18035,18037],{"class":72,"line":1890},[70,18034,8461],{"class":219},[70,18036,12464],{"class":76},[70,18038,14438],{"class":264},[70,18040,18041,18043],{"class":72,"line":5216},[70,18042,8472],{"class":124},[70,18044,562],{"class":264},[70,18046,18047],{"class":72,"line":5221},[70,18048,366],{"class":264},[70,18050,18051],{"class":72,"line":5231},[70,18052,252],{"emptyLinePlaceholder":251},[70,18054,18055],{"class":72,"line":5236},[70,18056,8384],{"class":219},[70,18058,18059,18061,18063],{"class":72,"line":5252},[70,18060,8223],{"class":219},[70,18062,10217],{"class":76},[70,18064,3162],{"class":264},[70,18066,18067],{"class":72,"line":5267},[70,18068,343],{"class":264},[70,18070,18071,18073,18075,18077,18079,18081,18083],{"class":72,"line":5272},[70,18072,7929],{"class":219},[70,18074,14475],{"class":264},[70,18076,14478],{"class":219},[70,18078,8269],{"class":219},[70,18080,14483],{"class":264},[70,18082,14486],{"class":76},[70,18084,8674],{"class":264},[70,18086,18087],{"class":72,"line":5281},[70,18088,7936],{"class":264},[70,18090,18091,18093],{"class":72,"line":6936},[70,18092,7971],{"class":219},[70,18094,314],{"class":264},[70,18096,18097],{"class":72,"line":6941},[70,18098,7978],{"class":264},[70,18100,18101],{"class":72,"line":6950},[70,18102,252],{"emptyLinePlaceholder":251},[70,18104,18105,18107,18109,18111,18113,18115],{"class":72,"line":6955},[70,18106,626],{"class":76},[70,18108,386],{"class":264},[70,18110,389],{"class":76},[70,18112,386],{"class":264},[70,18114,6084],{"class":76},[70,18116,620],{"class":264},[70,18118,18119],{"class":72,"line":6970},[70,18120,8421],{"class":264},[70,18122,18123,18125,18127,18129,18131,18133],{"class":72,"line":6985},[70,18124,1496],{"class":76},[70,18126,386],{"class":264},[70,18128,389],{"class":76},[70,18130,386],{"class":264},[70,18132,810],{"class":76},[70,18134,12447],{"class":264},[70,18136,18137],{"class":72,"line":6990},[70,18138,252],{"emptyLinePlaceholder":251},[70,18140,18141],{"class":72,"line":6999},[70,18142,18143],{"class":295},"            \u002F\u002F 读取完成的 handler 也绑定到同一个 strand。\n",[70,18145,18146,18148,18150,18152,18154,18157],{"class":72,"line":8599},[70,18147,1496],{"class":76},[70,18149,386],{"class":264},[70,18151,389],{"class":76},[70,18153,386],{"class":264},[70,18155,18156],{"class":76},"bind_executor",[70,18158,620],{"class":264},[70,18160,18161],{"class":72,"line":8604},[70,18162,18163],{"class":264},"                strand_,\n",[70,18165,18166,18168,18170,18172],{"class":72,"line":8615},[70,18167,8479],{"class":76},[70,18169,386],{"class":264},[70,18171,5144],{"class":76},[70,18173,620],{"class":264},[70,18175,18176,18179,18181],{"class":72,"line":8623},[70,18177,18178],{"class":219},"                    &",[70,18180,12464],{"class":76},[70,18182,10297],{"class":264},[70,18184,18185,18188],{"class":72,"line":8629},[70,18186,18187],{"class":124},"                    this",[70,18189,4555],{"class":264},[70,18191,18192,18195,18197,18199],{"class":72,"line":8634},[70,18193,18194],{"class":76},"                    std",[70,18196,386],{"class":264},[70,18198,5161],{"class":76},[70,18200,5164],{"class":264},[70,18202,18203,18205,18207,18209],{"class":72,"line":8640},[70,18204,18194],{"class":76},[70,18206,386],{"class":264},[70,18208,5161],{"class":76},[70,18210,18211],{"class":264},"::_2)));\n",[70,18213,18214],{"class":72,"line":8650},[70,18215,366],{"class":264},[70,18217,18218],{"class":72,"line":8655},[70,18219,252],{"emptyLinePlaceholder":251},[70,18221,18222,18224,18226],{"class":72,"line":8661},[70,18223,8223],{"class":219},[70,18225,6181],{"class":76},[70,18227,620],{"class":264},[70,18229,18230,18232,18234,18236,18238,18240,18242,18244,18246],{"class":72,"line":8677},[70,18231,7868],{"class":219},[70,18233,787],{"class":76},[70,18235,386],{"class":264},[70,18237,426],{"class":76},[70,18239,386],{"class":264},[70,18241,4546],{"class":76},[70,18243,4549],{"class":219},[70,18245,4552],{"class":270},[70,18247,4555],{"class":264},[70,18249,18250,18252,18254,18256,18258],{"class":72,"line":8682},[70,18251,488],{"class":76},[70,18253,386],{"class":264},[70,18255,779],{"class":219},[70,18257,4566],{"class":270},[70,18259,337],{"class":264},[70,18261,18262],{"class":72,"line":8689},[70,18263,343],{"class":264},[70,18265,18266,18268],{"class":72,"line":8694},[70,18267,7929],{"class":219},[70,18269,477],{"class":264},[70,18271,18272],{"class":72,"line":8699},[70,18273,7936],{"class":264},[70,18275,18276,18278,18280,18282],{"class":72,"line":8704},[70,18277,5156],{"class":76},[70,18279,386],{"class":264},[70,18281,444],{"class":76},[70,18283,620],{"class":264},[70,18285,18286,18289],{"class":72,"line":8709},[70,18287,18288],{"class":80},"                \"读取结束：{}，线程 id = {}\"",[70,18290,4555],{"class":264},[70,18292,18293,18295,18297],{"class":72,"line":8721},[70,18294,7958],{"class":264},[70,18296,503],{"class":76},[70,18298,6310],{"class":264},[70,18300,18301,18303,18305,18307,18309,18311],{"class":72,"line":8726},[70,18302,8479],{"class":76},[70,18304,386],{"class":264},[70,18306,15573],{"class":76},[70,18308,386],{"class":264},[70,18310,15578],{"class":76},[70,18312,506],{"class":264},[70,18314,18315],{"class":72,"line":8732},[70,18316,252],{"emptyLinePlaceholder":251},[70,18318,18319,18321],{"class":72,"line":8752},[70,18320,7971],{"class":219},[70,18322,314],{"class":264},[70,18324,18325],{"class":72,"line":8758},[70,18326,7978],{"class":264},[70,18328,18329],{"class":72,"line":8763},[70,18330,252],{"emptyLinePlaceholder":251},[70,18332,18333,18335,18337,18339],{"class":72,"line":8784},[70,18334,488],{"class":76},[70,18336,1803],{"class":264},[70,18338,1806],{"class":76},[70,18340,620],{"class":264},[70,18342,18343,18345,18347],{"class":72,"line":8789},[70,18344,12612],{"class":264},[70,18346,1812],{"class":76},[70,18348,6310],{"class":264},[70,18350,18351],{"class":72,"line":8802},[70,18352,8626],{"class":264},[70,18354,18355],{"class":72,"line":8807},[70,18356,252],{"emptyLinePlaceholder":251},[70,18358,18359,18361,18363,18365],{"class":72,"line":8820},[70,18360,488],{"class":76},[70,18362,386],{"class":264},[70,18364,444],{"class":76},[70,18366,620],{"class":264},[70,18368,18369,18372],{"class":72,"line":8825},[70,18370,18371],{"class":80},"            \"收到数据，bytes = {}，线程 id = {}，内容 = {}\"",[70,18373,4555],{"class":264},[70,18375,18376],{"class":72,"line":8838},[70,18377,10477],{"class":264},[70,18379,18380,18382,18384,18386,18388,18390],{"class":72,"line":8843},[70,18381,5156],{"class":76},[70,18383,386],{"class":264},[70,18385,15573],{"class":76},[70,18387,386],{"class":264},[70,18389,15578],{"class":76},[70,18391,6310],{"class":264},[70,18393,18394],{"class":72,"line":8848},[70,18395,8329],{"class":264},[70,18397,18398],{"class":72,"line":8859},[70,18399,252],{"emptyLinePlaceholder":251},[70,18401,18402,18404,18406,18408],{"class":72,"line":8864},[70,18403,7929],{"class":219},[70,18405,8350],{"class":264},[70,18407,8353],{"class":219},[70,18409,14774],{"class":264},[70,18411,18412],{"class":72,"line":8876},[70,18413,7936],{"class":264},[70,18415,18416,18418],{"class":72,"line":8881},[70,18417,14783],{"class":76},[70,18419,2240],{"class":264},[70,18421,18422],{"class":72,"line":8899},[70,18423,7978],{"class":264},[70,18425,18426],{"class":72,"line":8916},[70,18427,366],{"class":264},[70,18429,18430],{"class":72,"line":8933},[70,18431,252],{"emptyLinePlaceholder":251},[70,18433,18434,18436,18438,18440,18442,18444,18446,18448],{"class":72,"line":8938},[70,18435,8223],{"class":219},[70,18437,14804],{"class":76},[70,18439,265],{"class":264},[70,18441,2058],{"class":76},[70,18443,386],{"class":264},[70,18445,3196],{"class":76},[70,18447,3199],{"class":270},[70,18449,337],{"class":264},[70,18451,18452],{"class":72,"line":8953},[70,18453,343],{"class":264},[70,18455,18456,18458],{"class":72,"line":8958},[70,18457,7929],{"class":219},[70,18459,14827],{"class":264},[70,18461,18462],{"class":72,"line":8967},[70,18463,7936],{"class":264},[70,18465,18466,18468],{"class":72,"line":8972},[70,18467,7971],{"class":219},[70,18469,314],{"class":264},[70,18471,18472],{"class":72,"line":8983},[70,18473,7978],{"class":264},[70,18475,18476],{"class":72,"line":8991},[70,18477,252],{"emptyLinePlaceholder":251},[70,18479,18480,18482,18484,18486],{"class":72,"line":8996},[70,18481,488],{"class":76},[70,18483,386],{"class":264},[70,18485,444],{"class":76},[70,18487,620],{"class":264},[70,18489,18490,18493],{"class":72,"line":9005},[70,18491,18492],{"class":80},"            \"enqueue_write()，线程 id = {}\"",[70,18494,4555],{"class":264},[70,18496,18497,18499,18501,18503,18505,18507],{"class":72,"line":12894},[70,18498,5156],{"class":76},[70,18500,386],{"class":264},[70,18502,15573],{"class":76},[70,18504,386],{"class":264},[70,18506,15578],{"class":76},[70,18508,506],{"class":264},[70,18510,18511],{"class":72,"line":12899},[70,18512,252],{"emptyLinePlaceholder":251},[70,18514,18515,18517,18519],{"class":72,"line":12904},[70,18516,8261],{"class":219},[70,18518,8264],{"class":264},[70,18520,1689],{"class":219},[70,18522,18523,18526,18528,18530],{"class":72,"line":12910},[70,18524,18525],{"class":219},"            !",[70,18527,8272],{"class":264},[70,18529,8275],{"class":76},[70,18531,2240],{"class":264},[70,18533,18534],{"class":72,"line":12919},[70,18535,252],{"emptyLinePlaceholder":251},[70,18537,18538,18540,18542],{"class":72,"line":12924},[70,18539,8296],{"class":264},[70,18541,8299],{"class":76},[70,18543,8302],{"class":264},[70,18545,18546],{"class":72,"line":12930},[70,18547,252],{"emptyLinePlaceholder":251},[70,18549,18550,18552,18554,18556],{"class":72,"line":12945},[70,18551,7929],{"class":219},[70,18553,8350],{"class":264},[70,18555,8353],{"class":219},[70,18557,8356],{"class":264},[70,18559,18560],{"class":72,"line":12950},[70,18561,7936],{"class":264},[70,18563,18564,18566],{"class":72,"line":12957},[70,18565,8365],{"class":76},[70,18567,2240],{"class":264},[70,18569,18570],{"class":72,"line":12962},[70,18571,7978],{"class":264},[70,18573,18574],{"class":72,"line":12967},[70,18575,366],{"class":264},[70,18577,18578],{"class":72,"line":12972},[70,18579,252],{"emptyLinePlaceholder":251},[70,18581,18582,18584,18586],{"class":72,"line":12977},[70,18583,8223],{"class":219},[70,18585,8391],{"class":76},[70,18587,3162],{"class":264},[70,18589,18590],{"class":72,"line":12988},[70,18591,343],{"class":264},[70,18593,18594,18596,18598,18600,18602,18604],{"class":72,"line":12993},[70,18595,7929],{"class":219},[70,18597,14475],{"class":264},[70,18599,14478],{"class":219},[70,18601,14957],{"class":264},[70,18603,8275],{"class":76},[70,18605,8674],{"class":264},[70,18607,18608],{"class":72,"line":12998},[70,18609,7936],{"class":264},[70,18611,18612,18614],{"class":72,"line":13016},[70,18613,7971],{"class":219},[70,18615,314],{"class":264},[70,18617,18618],{"class":72,"line":13021},[70,18619,7978],{"class":264},[70,18621,18622],{"class":72,"line":13027},[70,18623,252],{"emptyLinePlaceholder":251},[70,18625,18626,18628,18630,18632,18634,18636],{"class":72,"line":13044},[70,18627,626],{"class":76},[70,18629,386],{"class":264},[70,18631,389],{"class":76},[70,18633,386],{"class":264},[70,18635,4446],{"class":76},[70,18637,620],{"class":264},[70,18639,18640],{"class":72,"line":13049},[70,18641,8421],{"class":264},[70,18643,18644,18646,18648,18650,18652,18654],{"class":72,"line":13054},[70,18645,1496],{"class":76},[70,18647,386],{"class":264},[70,18649,389],{"class":76},[70,18651,386],{"class":264},[70,18653,810],{"class":76},[70,18655,620],{"class":264},[70,18657,18658,18660,18662],{"class":72,"line":13075},[70,18659,8440],{"class":264},[70,18661,8443],{"class":76},[70,18663,8446],{"class":264},[70,18665,18666],{"class":72,"line":13080},[70,18667,252],{"emptyLinePlaceholder":251},[70,18669,18670],{"class":72,"line":13093},[70,18671,18672],{"class":295},"            \u002F\u002F 写完成 handler 同样绑定到 strand。\n",[70,18674,18675,18677,18679,18681,18683,18685],{"class":72,"line":13098},[70,18676,1496],{"class":76},[70,18678,386],{"class":264},[70,18680,389],{"class":76},[70,18682,386],{"class":264},[70,18684,18156],{"class":76},[70,18686,620],{"class":264},[70,18688,18689],{"class":72,"line":13111},[70,18690,18163],{"class":264},[70,18692,18693,18695,18697,18699],{"class":72,"line":13116},[70,18694,8479],{"class":76},[70,18696,386],{"class":264},[70,18698,5144],{"class":76},[70,18700,620],{"class":264},[70,18702,18703,18705,18707],{"class":72,"line":13129},[70,18704,18178],{"class":219},[70,18706,12464],{"class":76},[70,18708,8467],{"class":264},[70,18710,18711,18713],{"class":72,"line":13134},[70,18712,18187],{"class":124},[70,18714,4555],{"class":264},[70,18716,18717,18719,18721,18723],{"class":72,"line":13139},[70,18718,18194],{"class":76},[70,18720,386],{"class":264},[70,18722,5161],{"class":76},[70,18724,5164],{"class":264},[70,18726,18727,18729,18731,18733],{"class":72,"line":13150},[70,18728,18194],{"class":76},[70,18730,386],{"class":264},[70,18732,5161],{"class":76},[70,18734,18211],{"class":264},[70,18736,18737],{"class":72,"line":13155},[70,18738,366],{"class":264},[70,18740,18741],{"class":72,"line":13165},[70,18742,252],{"emptyLinePlaceholder":251},[70,18744,18745,18747,18749],{"class":72,"line":13170},[70,18746,8223],{"class":219},[70,18748,4528],{"class":76},[70,18750,620],{"class":264},[70,18752,18753,18755,18757,18759,18761,18763,18765,18767,18769],{"class":72,"line":13176},[70,18754,7868],{"class":219},[70,18756,787],{"class":76},[70,18758,386],{"class":264},[70,18760,426],{"class":76},[70,18762,386],{"class":264},[70,18764,4546],{"class":76},[70,18766,4549],{"class":219},[70,18768,4552],{"class":270},[70,18770,4555],{"class":264},[70,18772,18773,18775,18777,18779,18781],{"class":72,"line":13193},[70,18774,488],{"class":76},[70,18776,386],{"class":264},[70,18778,779],{"class":219},[70,18780,4566],{"class":270},[70,18782,337],{"class":264},[70,18784,18785],{"class":72,"line":13210},[70,18786,343],{"class":264},[70,18788,18789,18791],{"class":72,"line":13227},[70,18790,7929],{"class":219},[70,18792,477],{"class":264},[70,18794,18795],{"class":72,"line":13232},[70,18796,7936],{"class":264},[70,18798,18799,18801,18803,18805],{"class":72,"line":13243},[70,18800,5156],{"class":76},[70,18802,386],{"class":264},[70,18804,444],{"class":76},[70,18806,620],{"class":264},[70,18808,18809,18812],{"class":72,"line":13251},[70,18810,18811],{"class":80},"                \"发送结束：{}，线程 id = {}\"",[70,18813,4555],{"class":264},[70,18815,18816,18818,18820],{"class":72,"line":13256},[70,18817,7958],{"class":264},[70,18819,503],{"class":76},[70,18821,6310],{"class":264},[70,18823,18824,18826,18828,18830,18832,18834],{"class":72,"line":13265},[70,18825,8479],{"class":76},[70,18827,386],{"class":264},[70,18829,15573],{"class":76},[70,18831,386],{"class":264},[70,18833,15578],{"class":76},[70,18835,506],{"class":264},[70,18837,18838],{"class":72,"line":13270},[70,18839,252],{"emptyLinePlaceholder":251},[70,18841,18842,18844],{"class":72,"line":13285},[70,18843,7971],{"class":219},[70,18845,314],{"class":264},[70,18847,18848],{"class":72,"line":13290},[70,18849,7978],{"class":264},[70,18851,18852],{"class":72,"line":13299},[70,18853,252],{"emptyLinePlaceholder":251},[70,18855,18856,18858,18860,18862],{"class":72,"line":15222},[70,18857,488],{"class":76},[70,18859,386],{"class":264},[70,18861,444],{"class":76},[70,18863,620],{"class":264},[70,18865,18866,18869],{"class":72,"line":15227},[70,18867,18868],{"class":80},"            \"发送完成，bytes = {}，线程 id = {}\"",[70,18870,4555],{"class":264},[70,18872,18873],{"class":72,"line":15234},[70,18874,10477],{"class":264},[70,18876,18877,18879,18881,18883,18885,18887],{"class":72,"line":15239},[70,18878,5156],{"class":76},[70,18880,386],{"class":264},[70,18882,15573],{"class":76},[70,18884,386],{"class":264},[70,18886,15578],{"class":76},[70,18888,506],{"class":264},[70,18890,18891],{"class":72,"line":15244},[70,18892,252],{"emptyLinePlaceholder":251},[70,18894,18895,18897,18899],{"class":72,"line":15249},[70,18896,8296],{"class":264},[70,18898,8645],{"class":76},[70,18900,2240],{"class":264},[70,18902,18903],{"class":72,"line":15259},[70,18904,252],{"emptyLinePlaceholder":251},[70,18906,18907,18909,18911,18913,18915,18917],{"class":72,"line":15264},[70,18908,7929],{"class":219},[70,18910,8350],{"class":264},[70,18912,8353],{"class":219},[70,18914,8272],{"class":264},[70,18916,8275],{"class":76},[70,18918,8674],{"class":264},[70,18920,18921],{"class":72,"line":15271},[70,18922,7936],{"class":264},[70,18924,18925,18927],{"class":72,"line":15276},[70,18926,8365],{"class":76},[70,18928,2240],{"class":264},[70,18930,18931],{"class":72,"line":15283},[70,18932,7978],{"class":264},[70,18934,18935],{"class":72,"line":15288},[70,18936,366],{"class":264},[70,18938,18939],{"class":72,"line":15293},[70,18940,252],{"emptyLinePlaceholder":251},[70,18942,18943,18945,18947],{"class":72,"line":15306},[70,18944,8223],{"class":219},[70,18946,15254],{"class":76},[70,18948,3162],{"class":264},[70,18950,18951],{"class":72,"line":15311},[70,18952,343],{"class":264},[70,18954,18955,18957],{"class":72,"line":15322},[70,18956,7929],{"class":219},[70,18958,14827],{"class":264},[70,18960,18961],{"class":72,"line":15330},[70,18962,7936],{"class":264},[70,18964,18965,18967],{"class":72,"line":15335},[70,18966,7971],{"class":219},[70,18968,314],{"class":264},[70,18970,18971],{"class":72,"line":15346},[70,18972,7978],{"class":264},[70,18974,18975],{"class":72,"line":15351},[70,18976,252],{"emptyLinePlaceholder":251},[70,18978,18979,18981,18983,18985],{"class":72,"line":15362},[70,18980,15296],{"class":264},[70,18982,308],{"class":219},[70,18984,15301],{"class":124},[70,18986,314],{"class":264},[70,18988,18989],{"class":72,"line":15367},[70,18990,252],{"emptyLinePlaceholder":251},[70,18992,18993,18995,18997,18999],{"class":72,"line":15378},[70,18994,488],{"class":76},[70,18996,386],{"class":264},[70,18998,444],{"class":76},[70,19000,620],{"class":264},[70,19002,19003,19006],{"class":72,"line":15383},[70,19004,19005],{"class":80},"            \"关闭串口，线程 id = {}\"",[70,19007,4555],{"class":264},[70,19009,19010,19012,19014,19016,19018,19020],{"class":72,"line":15393},[70,19011,5156],{"class":76},[70,19013,386],{"class":264},[70,19015,15573],{"class":76},[70,19017,386],{"class":264},[70,19019,15578],{"class":76},[70,19021,506],{"class":264},[70,19023,19024],{"class":72,"line":15398},[70,19025,252],{"emptyLinePlaceholder":251},[70,19027,19028,19030,19032,19034],{"class":72,"line":15403},[70,19029,626],{"class":76},[70,19031,386],{"class":264},[70,19033,426],{"class":76},[70,19035,429],{"class":264},[70,19037,19038],{"class":72,"line":15408},[70,19039,252],{"emptyLinePlaceholder":251},[70,19041,19042,19044,19046],{"class":72,"line":15425},[70,19043,7916],{"class":264},[70,19045,15356],{"class":76},[70,19047,15359],{"class":264},[70,19049,19050],{"class":72,"line":15430},[70,19051,252],{"emptyLinePlaceholder":251},[70,19053,19054,19056,19058],{"class":72,"line":15441},[70,19055,15370],{"class":264},[70,19057,15373],{"class":76},[70,19059,2240],{"class":264},[70,19061,19062],{"class":72,"line":15446},[70,19063,252],{"emptyLinePlaceholder":251},[70,19065,19066,19068,19070],{"class":72,"line":15463},[70,19067,7916],{"class":264},[70,19069,15388],{"class":76},[70,19071,15359],{"class":264},[70,19073,19074],{"class":72,"line":15468},[70,19075,366],{"class":264},[70,19077,19078],{"class":72,"line":15485},[70,19079,252],{"emptyLinePlaceholder":251},[70,19081,19082],{"class":72,"line":15490},[70,19083,8384],{"class":219},[70,19085,19086,19088,19090,19092,19095],{"class":72,"line":15506},[70,19087,383],{"class":76},[70,19089,386],{"class":264},[70,19091,389],{"class":76},[70,19093,19094],{"class":264},"::strand",[70,19096,19097],{"class":219},"\u003C\n",[70,19099,19100,19102,19104,19106,19108,19110,19113],{"class":72,"line":15511},[70,19101,626],{"class":76},[70,19103,386],{"class":264},[70,19105,389],{"class":76},[70,19107,386],{"class":264},[70,19109,7856],{"class":76},[70,19111,19112],{"class":264},"::executor_type",[70,19114,19115],{"class":219},">\n",[70,19117,19118],{"class":72,"line":15516},[70,19119,19120],{"class":264},"        strand_;\n",[70,19122,19123],{"class":72,"line":15542},[70,19124,252],{"emptyLinePlaceholder":251},[70,19126,19127,19129,19131,19133],{"class":72,"line":15547},[70,19128,383],{"class":76},[70,19130,386],{"class":264},[70,19132,389],{"class":76},[70,19134,8718],{"class":264},[70,19136,19137],{"class":72,"line":15558},[70,19138,252],{"emptyLinePlaceholder":251},[70,19140,19141,19143,19145,19147,19149,19151,19153],{"class":72,"line":15566},[70,19142,302],{"class":76},[70,19144,1623],{"class":264},[70,19146,1626],{"class":219},[70,19148,274],{"class":264},[70,19150,1631],{"class":124},[70,19152,1634],{"class":219},[70,19154,13013],{"class":264},[70,19156,19157],{"class":72,"line":15583},[70,19158,252],{"emptyLinePlaceholder":251},[70,19160,19161,19163,19165,19167,19169,19171,19173],{"class":72,"line":15588},[70,19162,302],{"class":76},[70,19164,8737],{"class":264},[70,19166,6226],{"class":219},[70,19168,2058],{"class":76},[70,19170,8744],{"class":264},[70,19172,1634],{"class":219},[70,19174,8749],{"class":264},[70,19176,19177],{"class":72,"line":15598},[70,19178,252],{"emptyLinePlaceholder":251},[70,19180,19181,19183,19185,19187,19189],{"class":72,"line":15603},[70,19182,15493],{"class":219},[70,19184,15496],{"class":264},[70,19186,308],{"class":219},[70,19188,15501],{"class":124},[70,19190,314],{"class":264},[70,19192,19193],{"class":72,"line":15614},[70,19194,8755],{"class":264},[70,19196,19197],{"class":72,"line":15622},[70,19198,252],{"emptyLinePlaceholder":251},[70,19200,19201,19203,19205],{"class":72,"line":15627},[70,19202,4525],{"class":219},[70,19204,15521],{"class":76},[70,19206,620],{"class":264},[70,19208,19209,19211,19213,19215,19217,19219,19221,19223],{"class":72,"line":15632},[70,19210,383],{"class":76},[70,19212,386],{"class":264},[70,19214,389],{"class":76},[70,19216,386],{"class":264},[70,19218,7856],{"class":76},[70,19220,6238],{"class":219},[70,19222,7861],{"class":270},[70,19224,4555],{"class":264},[70,19226,19227,19229,19231,19233,19235,19237,19240],{"class":72,"line":15653},[70,19228,4535],{"class":219},[70,19230,7871],{"class":76},[70,19232,386],{"class":264},[70,19234,3196],{"class":76},[70,19236,4549],{"class":219},[70,19238,19239],{"class":270}," name",[70,19241,337],{"class":264},[70,19243,19244],{"class":72,"line":15658},[70,19245,289],{"class":264},[70,19247,19248,19250,19252,19254],{"class":72,"line":15671},[70,19249,302],{"class":76},[70,19251,386],{"class":264},[70,19253,444],{"class":76},[70,19255,620],{"class":264},[70,19257,19258,19261],{"class":72,"line":15676},[70,19259,19260],{"class":80},"        \"{}：开始 io.run()，线程 id = {}\"",[70,19262,4555],{"class":264},[70,19264,19265],{"class":72,"line":15689},[70,19266,19267],{"class":264},"        name,\n",[70,19269,19270,19272,19274,19276,19278,19280],{"class":72,"line":15694},[70,19271,488],{"class":76},[70,19273,386],{"class":264},[70,19275,15573],{"class":76},[70,19277,386],{"class":264},[70,19279,15578],{"class":76},[70,19281,506],{"class":264},[70,19283,19284],{"class":72,"line":15707},[70,19285,252],{"emptyLinePlaceholder":251},[70,19287,19288,19290,19292],{"class":72,"line":15712},[70,19289,15591],{"class":264},[70,19291,2237],{"class":76},[70,19293,2240],{"class":264},[70,19295,19296],{"class":72,"line":15717},[70,19297,252],{"emptyLinePlaceholder":251},[70,19299,19300,19302,19304,19306],{"class":72,"line":15728},[70,19301,302],{"class":76},[70,19303,386],{"class":264},[70,19305,444],{"class":76},[70,19307,620],{"class":264},[70,19309,19310,19313],{"class":72,"line":15733},[70,19311,19312],{"class":80},"        \"{}：io.run() 返回\"",[70,19314,4555],{"class":264},[70,19316,19317],{"class":72,"line":15739},[70,19318,19319],{"class":264},"        name);\n",[70,19321,19322],{"class":72,"line":15745},[70,19323,920],{"class":264},[70,19325,19326],{"class":72,"line":15756},[70,19327,252],{"emptyLinePlaceholder":251},[70,19329,19330,19332,19334,19336,19338,19340,19342,19344,19346],{"class":72,"line":15772},[70,19331,258],{"class":219},[70,19333,261],{"class":76},[70,19335,265],{"class":264},[70,19337,258],{"class":219},[70,19339,271],{"class":270},[70,19341,274],{"class":264},[70,19343,277],{"class":219},[70,19345,280],{"class":270},[70,19347,283],{"class":264},[70,19349,19350],{"class":72,"line":15777},[70,19351,289],{"class":264},[70,19353,19354,19356,19358,19360,19362],{"class":72,"line":15786},[70,19355,302],{"class":76},[70,19357,305],{"class":264},[70,19359,308],{"class":219},[70,19361,311],{"class":80},[70,19363,314],{"class":264},[70,19365,19366],{"class":72,"line":15791},[70,19367,252],{"emptyLinePlaceholder":251},[70,19369,19370,19372,19374,19376,19378],{"class":72,"line":15797},[70,19371,325],{"class":219},[70,19373,328],{"class":264},[70,19375,331],{"class":219},[70,19377,334],{"class":124},[70,19379,337],{"class":264},[70,19381,19382],{"class":72,"line":15810},[70,19383,343],{"class":264},[70,19385,19386,19388,19390,19392,19394],{"class":72,"line":15821},[70,19387,349],{"class":264},[70,19389,308],{"class":219},[70,19391,354],{"class":264},[70,19393,357],{"class":124},[70,19395,360],{"class":264},[70,19397,19398],{"class":72,"line":15827},[70,19399,366],{"class":264},[70,19401,19402],{"class":72,"line":15835},[70,19403,252],{"emptyLinePlaceholder":251},[70,19405,19406,19408,19410,19412],{"class":72,"line":15840},[70,19407,383],{"class":76},[70,19409,386],{"class":264},[70,19411,389],{"class":76},[70,19413,392],{"class":264},[70,19415,19416],{"class":72,"line":15846},[70,19417,252],{"emptyLinePlaceholder":251},[70,19419,19420,19422,19424],{"class":72,"line":15852},[70,19421,15748],{"class":219},[70,19423,15751],{"class":264},[70,19425,1689],{"class":219},[70,19427,19428,19430,19432,19434,19436,19438],{"class":72,"line":15862},[70,19429,626],{"class":76},[70,19431,386],{"class":264},[70,19433,389],{"class":76},[70,19435,386],{"class":264},[70,19437,15767],{"class":76},[70,19439,416],{"class":264},[70,19441,19442],{"class":72,"line":15867},[70,19443,252],{"emptyLinePlaceholder":251},[70,19445,19446,19448,19450],{"class":72,"line":15878},[70,19447,13158],{"class":264},[70,19449,413],{"class":76},[70,19451,8873],{"class":264},[70,19453,19454],{"class":72,"line":15886},[70,19455,252],{"emptyLinePlaceholder":251},[70,19457,19458],{"class":72,"line":15901},[70,19459,19460],{"class":295},"    \u002F\u002F 两个线程同时运行同一个 io_context。\n",[70,19462,19463,19465,19467,19470],{"class":72,"line":15906},[70,19464,302],{"class":76},[70,19466,15802],{"class":264},[70,19468,19469],{"class":76},"t1",[70,19471,620],{"class":264},[70,19473,19474,19476,19478,19480],{"class":72,"line":15912},[70,19475,488],{"class":76},[70,19477,386],{"class":264},[70,19479,5144],{"class":76},[70,19481,620],{"class":264},[70,19483,19484],{"class":72,"line":15929},[70,19485,15824],{"class":264},[70,19487,19488,19490],{"class":72,"line":15946},[70,19489,6893],{"class":219},[70,19491,19492],{"class":264},"io,\n",[70,19494,19495,19497,19499,19501,19503,19506],{"class":72,"line":15963},[70,19496,5156],{"class":76},[70,19498,386],{"class":264},[70,19500,3196],{"class":76},[70,19502,265],{"class":264},[70,19504,19505],{"class":80},"\"Asio线程1\"",[70,19507,19508],{"class":264},")));\n",[70,19510,19511],{"class":72,"line":15968},[70,19512,252],{"emptyLinePlaceholder":251},[70,19514,19515,19517,19519,19522],{"class":72,"line":15979},[70,19516,302],{"class":76},[70,19518,15802],{"class":264},[70,19520,19521],{"class":76},"t2",[70,19523,620],{"class":264},[70,19525,19526,19528,19530,19532],{"class":72,"line":15987},[70,19527,488],{"class":76},[70,19529,386],{"class":264},[70,19531,5144],{"class":76},[70,19533,620],{"class":264},[70,19535,19536],{"class":72,"line":15992},[70,19537,15824],{"class":264},[70,19539,19540,19542],{"class":72,"line":16003},[70,19541,6893],{"class":219},[70,19543,19492],{"class":264},[70,19545,19546,19548,19550,19552,19554,19557],{"class":72,"line":16011},[70,19547,5156],{"class":76},[70,19549,386],{"class":264},[70,19551,3196],{"class":76},[70,19553,265],{"class":264},[70,19555,19556],{"class":80},"\"Asio线程2\"",[70,19558,19508],{"class":264},[70,19560,19561],{"class":72,"line":16016},[70,19562,252],{"emptyLinePlaceholder":251},[70,19564,19565,19567,19569],{"class":72,"line":16024},[70,19566,463],{"class":264},[70,19568,15857],{"class":76},[70,19570,2240],{"class":264},[70,19572,19573],{"class":72,"line":16041},[70,19574,252],{"emptyLinePlaceholder":251},[70,19576,19577,19579,19581,19583,19585,19587,19589],{"class":72,"line":16046},[70,19578,463],{"class":264},[70,19580,7685],{"class":76},[70,19582,265],{"class":264},[70,19584,7690],{"class":80},[70,19586,753],{"class":124},[70,19588,756],{"class":80},[70,19590,898],{"class":264},[70,19592,19593,19595,19597,19599,19601,19603,19605],{"class":72,"line":16052},[70,19594,463],{"class":264},[70,19596,7685],{"class":76},[70,19598,265],{"class":264},[70,19600,7705],{"class":80},[70,19602,753],{"class":124},[70,19604,756],{"class":80},[70,19606,898],{"class":264},[70,19608,19609,19611,19613,19615,19617,19619,19621],{"class":72,"line":16062},[70,19610,463],{"class":264},[70,19612,7685],{"class":76},[70,19614,265],{"class":264},[70,19616,7720],{"class":80},[70,19618,753],{"class":124},[70,19620,756],{"class":80},[70,19622,898],{"class":264},[70,19624,19625],{"class":72,"line":16067},[70,19626,252],{"emptyLinePlaceholder":251},[70,19628,19629,19631,19633,19635],{"class":72,"line":16073},[70,19630,302],{"class":76},[70,19632,386],{"class":264},[70,19634,444],{"class":76},[70,19636,620],{"class":264},[70,19638,19639,19642],{"class":72,"line":16084},[70,19640,19641],{"class":80},"        \"main：两个 Asio 线程正在运行，按 Enter 结束\"",[70,19643,898],{"class":264},[70,19645,19646],{"class":72,"line":16089},[70,19647,252],{"emptyLinePlaceholder":251},[70,19649,19650,19652],{"class":72,"line":16100},[70,19651,302],{"class":76},[70,19653,16021],{"class":264},[70,19655,19656,19658,19660,19662,19664,19666],{"class":72,"line":16105},[70,19657,302],{"class":76},[70,19659,386],{"class":264},[70,19661,16031],{"class":76},[70,19663,265],{"class":264},[70,19665,2058],{"class":76},[70,19667,16038],{"class":264},[70,19669,19670],{"class":72,"line":16120},[70,19671,252],{"emptyLinePlaceholder":251},[70,19673,19674,19676,19678],{"class":72,"line":16125},[70,19675,463],{"class":264},[70,19677,16057],{"class":76},[70,19679,2240],{"class":264},[70,19681,19682],{"class":72,"line":16134},[70,19683,252],{"emptyLinePlaceholder":251},[70,19685,19687,19689,19691],{"class":72,"line":19686},304,[70,19688,16076],{"class":264},[70,19690,16079],{"class":76},[70,19692,2240],{"class":264},[70,19694,19696],{"class":72,"line":19695},305,[70,19697,252],{"emptyLinePlaceholder":251},[70,19699,19701,19704,19706],{"class":72,"line":19700},306,[70,19702,19703],{"class":264},"    t1.",[70,19705,16095],{"class":76},[70,19707,2240],{"class":264},[70,19709,19711,19714,19716],{"class":72,"line":19710},307,[70,19712,19713],{"class":264},"    t2.",[70,19715,16095],{"class":76},[70,19717,2240],{"class":264},[70,19719,19721],{"class":72,"line":19720},308,[70,19722,252],{"emptyLinePlaceholder":251},[70,19724,19726,19728,19730,19732,19734,19736],{"class":72,"line":19725},309,[70,19727,302],{"class":76},[70,19729,386],{"class":264},[70,19731,444],{"class":76},[70,19733,265],{"class":264},[70,19735,895],{"class":80},[70,19737,898],{"class":264},[70,19739,19741],{"class":72,"line":19740},310,[70,19742,252],{"emptyLinePlaceholder":251},[70,19744,19746,19748,19750],{"class":72,"line":19745},311,[70,19747,909],{"class":219},[70,19749,912],{"class":124},[70,19751,314],{"class":264},[70,19753,19755],{"class":72,"line":19754},312,[70,19756,920],{"class":264},[55,19758,930],{"id":19759},"编译运行-8",[15,19761,9013],{},[22,19763,19764],{"className":64,"code":115,"language":66,"meta":28,"style":28},[30,19765,19766,19776,19782],{"__ignoreMap":28},[70,19767,19768,19770,19772,19774],{"class":72,"line":73},[70,19769,52],{"class":76},[70,19771,125],{"class":124},[70,19773,125],{"class":124},[70,19775,130],{"class":124},[70,19777,19778,19780],{"class":72,"line":133},[70,19779,136],{"class":80},[70,19781,130],{"class":124},[70,19783,19784],{"class":72,"line":141},[70,19785,144],{"class":80},[15,19787,19788],{},"终端 2：",[22,19790,19791],{"className":64,"code":963,"language":66,"meta":28,"style":28},[30,19792,19793],{"__ignoreMap":28},[70,19794,19795,19797],{"class":72,"line":73},[70,19796,970],{"class":76},[70,19798,973],{"class":80},[15,19800,19801],{},"编译并运行程序",[15,19803,19804],{},"如果测试接收：",[22,19806,19807],{"className":64,"code":13362,"language":66,"meta":28,"style":28},[30,19808,19809],{"__ignoreMap":28},[70,19810,19811,19813,19815,19817],{"class":72,"line":73},[70,19812,10778],{"class":124},[70,19814,10781],{"class":80},[70,19816,1976],{"class":219},[70,19818,973],{"class":80},[55,19820,19822,19823,19825],{"id":19821},"为什么示例-8-不需要-strand示例-9-却需要","为什么示例 8 不需要 ",[30,19824,17256],{},"，示例 9 却需要？",[15,19827,19828],{},"示例 8：",[22,19830,19833],{"className":19831,"code":19832,"language":27,"meta":28},[25],"只有一个线程\n\n↓\nio.run()\n",[30,19834,19832],{"__ignoreMap":28},[15,19836,19837],{},"因此所有 Asio handler：",[22,19839,19842],{"className":19840,"code":19841,"language":27,"meta":28},[25],"handler A\n↓\nhandler B\n↓\nhandler C\n",[30,19843,19841],{"__ignoreMap":28},[15,19845,19846],{},"只能一个一个执行。",[15,19848,3803],{},[22,19850,19852],{"className":210,"code":19851,"language":212,"meta":28,"style":28},"boost::asio::post(io, handler);\n",[30,19853,19854],{"__ignoreMap":28},[70,19855,19856,19858,19860,19862,19864,19866],{"class":72,"line":73},[70,19857,540],{"class":76},[70,19859,386],{"class":264},[70,19861,389],{"class":76},[70,19863,386],{"class":264},[70,19865,14251],{"class":76},[70,19867,19868],{"class":264},"(io, handler);\n",[15,19870,19871],{},"投递了很多任务，它们最终还是由：",[22,19873,19876],{"className":19874,"code":19875,"language":27,"meta":28},[25],"唯一一个 Asio线程\n",[30,19877,19875],{"__ignoreMap":28},[15,19879,19880],{},"执行。",[15,19882,2160],{},[22,19884,19887],{"className":19885,"code":19886,"language":27,"meta":28},[25],"write_queue_\nread_buffer_\nstopping_\n",[30,19888,19886],{"__ignoreMap":28},[15,19890,19891],{},"不会被两个 Asio handler 同时访问。",[40,19893],{},[15,19895,19896],{},"示例 9：",[22,19898,19900],{"className":19899,"code":17316,"language":27,"meta":28},[25],[30,19901,17316],{"__ignoreMap":28},[15,19903,19904,19905,19907],{},"此时 ",[30,19906,7856],{}," 可以同时调度两个 handler。",[15,19909,2746],{},[22,19911,19914],{"className":19912,"code":19913,"language":27,"meta":28},[25],"时间 ─────────────────────────→\n\n线程1：[ enqueue_write()          ]\n\n线程2：      [ on_write()             ]\n                   ↑\n                发生重叠\n",[30,19915,19913],{"__ignoreMap":28},[15,19917,19918],{},"两个函数都可能操作：",[22,19920,19921],{"className":210,"code":13560,"language":212,"meta":28,"style":28},[30,19922,19923],{"__ignoreMap":28},[70,19924,19925],{"class":72,"line":73},[70,19926,13560],{"class":264},[15,19928,19929],{},"于是产生数据竞争。",[40,19931],{},[55,19933,19935,19937],{"id":19934},"strand-在这里发挥什么作用",[30,19936,17256],{}," 在这里发挥什么作用？",[15,19939,19940],{},"创建：",[22,19942,19944],{"className":210,"code":19943,"language":212,"meta":28,"style":28},"strand_(boost::asio::make_strand(io))\n",[30,19945,19946],{"__ignoreMap":28},[70,19947,19948,19950,19952,19954,19956,19958,19960,19962],{"class":72,"line":73},[70,19949,17492],{"class":76},[70,19951,265],{"class":264},[70,19953,540],{"class":76},[70,19955,386],{"class":264},[70,19957,389],{"class":76},[70,19959,386],{"class":264},[70,19961,17505],{"class":76},[70,19963,19964],{"class":264},"(io))\n",[15,19966,19967],{},"然后所有与：",[22,19969,19972],{"className":19970,"code":19971,"language":27,"meta":28},[25],"AsyncSerialPort 内部状态\n",[30,19973,19971],{"__ignoreMap":28},[15,19975,19976],{},"有关的 handler 都放到：",[22,19978,19980],{"className":210,"code":19979,"language":212,"meta":28,"style":28},"strand_\n",[30,19981,19982],{"__ignoreMap":28},[70,19983,19984],{"class":72,"line":73},[70,19985,19979],{"class":264},[15,19987,19988],{},"上。",[15,19990,2746],{},[22,19992,19994],{"className":210,"code":19993,"language":212,"meta":28,"style":28},"boost::asio::post(\n    strand_,\n    handler);\n",[30,19995,19996,20010,20015],{"__ignoreMap":28},[70,19997,19998,20000,20002,20004,20006,20008],{"class":72,"line":73},[70,19999,540],{"class":76},[70,20001,386],{"class":264},[70,20003,389],{"class":76},[70,20005,386],{"class":264},[70,20007,14251],{"class":76},[70,20009,620],{"class":264},[70,20011,20012],{"class":72,"line":133},[70,20013,20014],{"class":264},"    strand_,\n",[70,20016,20017],{"class":72,"line":141},[70,20018,5998],{"class":264},[15,20020,20021],{},"以及：",[22,20023,20025],{"className":210,"code":20024,"language":212,"meta":28,"style":28},"boost::asio::bind_executor(\n    strand_,\n    handler);\n",[30,20026,20027,20041,20045],{"__ignoreMap":28},[70,20028,20029,20031,20033,20035,20037,20039],{"class":72,"line":73},[70,20030,540],{"class":76},[70,20032,386],{"class":264},[70,20034,389],{"class":76},[70,20036,386],{"class":264},[70,20038,18156],{"class":76},[70,20040,620],{"class":264},[70,20042,20043],{"class":72,"line":133},[70,20044,20014],{"class":264},[70,20046,20047],{"class":72,"line":141},[70,20048,5998],{"class":264},[15,20050,16507],{},[22,20052,20055],{"className":20053,"code":20054,"language":27,"meta":28},[25],"enqueue_write() ─┐\non_write()       ├── 同一个 strand\non_read()        │\ndo_stop()        ┘\n",[30,20056,20054],{"__ignoreMap":28},[15,20058,20059],{},"strand 保证：",[12,20061,20062],{},[15,20063,20064],{},"这些 handler 不会彼此并发执行。",[15,20066,20067],{},"所以即使：",[22,20069,20072],{"className":20070,"code":20071,"language":27,"meta":28},[25],"线程1\n\n线程2\n",[30,20073,20071],{"__ignoreMap":28},[15,20075,20076],{},"都在执行：",[22,20078,20079],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,20080,20081],{"__ignoreMap":28},[70,20082,20083,20085,20087],{"class":72,"line":73},[70,20084,2234],{"class":264},[70,20086,2237],{"class":76},[70,20088,2240],{"class":264},[15,20090,20091],{},"也只能出现：",[22,20093,20096],{"className":20094,"code":20095,"language":27,"meta":28},[25],"线程1：\n[ enqueue_write() ]\n\n线程2：\n                   [ on_write() ]\n",[30,20097,20095],{"__ignoreMap":28},[15,20099,2599],{},[22,20101,20104],{"className":20102,"code":20103,"language":27,"meta":28},[25],"线程2：\n[ on_write() ]\n\n线程1：\n              [ on_read() ]\n",[30,20105,20103],{"__ignoreMap":28},[15,20107,20108],{},"而不会：",[22,20110,20113],{"className":20111,"code":20112,"language":27,"meta":28},[25],"线程1：\n[ enqueue_write()        ]\n\n线程2：\n       [ on_write()          ]\n            ↑\n          重叠执行\n",[30,20114,20112],{"__ignoreMap":28},[40,20116],{},[55,20118,20120,20122],{"id":20119},"strand-不是把串口固定到某一个线程",[30,20121,17256],{}," 不是把串口固定到某一个线程",[15,20124,20125],{},"这一点非常重要。",[15,20127,20128],{},"可能第一次：",[22,20130,20132],{"className":20131,"code":7289,"language":27,"meta":28},[25],[30,20133,7289],{"__ignoreMap":28},[15,20135,20136],{},"在线程 1 执行。",[15,20138,11472],{},[22,20140,20142],{"className":20141,"code":7289,"language":27,"meta":28},[25],[30,20143,7289],{"__ignoreMap":28},[15,20145,20146],{},"在线程 2 执行。",[15,20148,20149],{},"例如输出可能是：",[22,20151,20154],{"className":20152,"code":20153,"language":27,"meta":28},[25],"收到数据，线程 id = 111111\n\n发送完成，线程 id = 222222\n\n收到数据，线程 id = 222222\n\n发送完成，线程 id = 111111\n",[30,20155,20153],{"__ignoreMap":28},[15,20157,20158],{},"这是完全正常的。",[15,20160,20161],{},"strand 保证的是：",[22,20163,20166],{"className":20164,"code":20165,"language":27,"meta":28},[25],"执行时间不重叠\n",[30,20167,20165],{"__ignoreMap":28},[15,20169,9614],{},[22,20171,20174],{"className":20172,"code":20173,"language":27,"meta":28},[25],"永远固定在线程1\n",[30,20175,20173],{"__ignoreMap":28},[15,20177,2160],{},[22,20179,20182],{"className":20180,"code":20181,"language":27,"meta":28},[25],"strand\n≠ 固定线程\n\nstrand\n= 串行化一组 handler\n",[30,20183,20181],{"__ignoreMap":28},[40,20185],{},[55,20187,20189,20190,3254,20193,20195],{"id":20188},"为什么不仅-on_read-on_write-要绑定-strand","为什么不仅 ",[30,20191,20192],{},"on_read()",[30,20194,9644],{}," 要绑定 strand？",[15,20197,20198],{},"假设我们只写：",[22,20200,20202],{"className":210,"code":20201,"language":212,"meta":28,"style":28},"boost::asio::bind_executor(\n    strand_,\n    on_write_handler);\n",[30,20203,20204,20218,20222],{"__ignoreMap":28},[70,20205,20206,20208,20210,20212,20214,20216],{"class":72,"line":73},[70,20207,540],{"class":76},[70,20209,386],{"class":264},[70,20211,389],{"class":76},[70,20213,386],{"class":264},[70,20215,18156],{"class":76},[70,20217,620],{"class":264},[70,20219,20220],{"class":72,"line":133},[70,20221,20014],{"class":264},[70,20223,20224],{"class":72,"line":141},[70,20225,20226],{"class":264},"    on_write_handler);\n",[15,20228,3999],{},[22,20230,20231],{"className":210,"code":16345,"language":212,"meta":28,"style":28},[30,20232,20233],{"__ignoreMap":28},[70,20234,20235,20237],{"class":72,"line":73},[70,20236,7685],{"class":76},[70,20238,3162],{"class":264},[15,20240,20241],{},"仍然：",[22,20243,20245],{"className":210,"code":20244,"language":212,"meta":28,"style":28},"boost::asio::post(\n    io,\n    enqueue_write_handler);\n",[30,20246,20247,20261,20266],{"__ignoreMap":28},[70,20248,20249,20251,20253,20255,20257,20259],{"class":72,"line":73},[70,20250,540],{"class":76},[70,20252,386],{"class":264},[70,20254,389],{"class":76},[70,20256,386],{"class":264},[70,20258,14251],{"class":76},[70,20260,620],{"class":264},[70,20262,20263],{"class":72,"line":133},[70,20264,20265],{"class":264},"    io,\n",[70,20267,20268],{"class":72,"line":141},[70,20269,20270],{"class":264},"    enqueue_write_handler);\n",[15,20272,11261],{},[22,20274,20276],{"className":20275,"code":16601,"language":27,"meta":28},[25],[30,20277,16601],{"__ignoreMap":28},[15,20279,20280],{},"没有经过 strand。",[15,20282,20283],{},"两个 Asio 线程仍然可能出现：",[22,20285,20288],{"className":20286,"code":20287,"language":27,"meta":28},[25],"线程1：\nenqueue_write()\n↓\npush_back()\n\n线程2：\non_write()\n↓\npop_front()\n",[30,20289,20287],{"__ignoreMap":28},[15,20291,20292],{},"所以还不安全。",[15,20294,20295],{},"因此只要一个操作会访问：",[22,20297,20300],{"className":20298,"code":20299,"language":27,"meta":28},[25],"AsyncSerialPort 的共享内部状态\n",[30,20301,20299],{"__ignoreMap":28},[15,20303,20304],{},"就应该让它遵守同一个：",[22,20306,20307],{"className":210,"code":19979,"language":212,"meta":28,"style":28},[30,20308,20309],{"__ignoreMap":28},[70,20310,20311],{"class":72,"line":73},[70,20312,19979],{"class":264},[15,20314,20315],{},"本例因此统一使用：",[22,20317,20320],{"className":20318,"code":20319,"language":27,"meta":28},[25],"start()\n↓\npost(strand_)\n\nasync_send()\n↓\npost(strand_)\n\nstop()\n↓\npost(strand_)\n\non_read()\n↓\nbind_executor(strand_)\n\non_write()\n↓\nbind_executor(strand_)\n",[30,20321,20319],{"__ignoreMap":28},[15,20323,13753],{},[22,20325,20328],{"className":20326,"code":20327,"language":27,"meta":28},[25],"write_queue_\nread_buffer_\nstopping_\nserial_ 的异步状态变化\n",[30,20329,20327],{"__ignoreMap":28},[15,20331,20332],{},"都处于同一套串行化规则中。",[40,20334],{},[55,20336,20338,20339,20341,20342,11288],{"id":20337},"那这里能不能不用-strand改用-mutex","那这里能不能不用 ",[30,20340,17256],{},"，改用 ",[30,20343,13542],{},[15,20345,20346],{},"可以。",[15,20348,2746],{},[22,20350,20351],{"className":210,"code":16415,"language":212,"meta":28,"style":28},[30,20352,20353],{"__ignoreMap":28},[70,20354,20355,20357],{"class":72,"line":73},[70,20356,2058],{"class":76},[70,20358,16424],{"class":264},[15,20360,20361],{},"然后每次访问：",[22,20363,20364],{"className":210,"code":13560,"language":212,"meta":28,"style":28},[30,20365,20366],{"__ignoreMap":28},[70,20367,20368],{"class":72,"line":73},[70,20369,13560],{"class":264},[15,20371,20372],{},"都：",[22,20374,20376],{"className":210,"code":20375,"language":212,"meta":28,"style":28},"std::scoped_lock lock(mutex_);\n",[30,20377,20378],{"__ignoreMap":28},[70,20379,20380,20382,20384,20387,20390,20392,20395],{"class":72,"line":73},[70,20381,2058],{"class":76},[70,20383,386],{"class":264},[70,20385,20386],{"class":76},"scoped_lock",[70,20388,20389],{"class":76}," lock",[70,20391,265],{"class":264},[70,20393,20394],{"class":76},"mutex_",[70,20396,898],{"class":264},[15,20398,20399],{},"理论上也可以保护共享状态。",[15,20401,20402],{},"但是这个类的情况是：",[22,20404,20407],{"className":20405,"code":20406,"language":27,"meta":28},[25],"大量内部状态变化\n\n本来就是由 Asio handler 驱动\n",[30,20408,20406],{"__ignoreMap":28},[15,20410,20411],{},"包括：",[22,20413,20416],{"className":20414,"code":20415,"language":27,"meta":28},[25],"enqueue_write()\non_write()\non_read()\nstop()\n",[30,20417,20415],{"__ignoreMap":28},[15,20419,20420],{},"因此直接规定：",[12,20422,20423],{},[15,20424,20425],{},"这些 handler 全部通过同一个 strand 串行执行。",[15,20427,20428],{},"通常比：",[22,20430,20433],{"className":20431,"code":20432,"language":27,"meta":28},[25],"这里 lock\n那里 unlock\n这个变量锁一下\n那个状态再考虑另一个锁\n",[30,20434,20432],{"__ignoreMap":28},[15,20436,20437],{},"更加自然。",[15,20439,20440],{},"可以这样区分：",[22,20442,20445],{"className":20443,"code":20444,"language":27,"meta":28},[25],"mutex\n→ 保护某一段共享代码 \u002F 数据\n\nstrand\n→ 串行化一组 Asio handler\n",[30,20446,20444],{"__ignoreMap":28},[40,20448],{},[55,20450,20452],{"id":20451},"示例-8-和示例-9-的核心区别","示例 8 和示例 9 的核心区别",[15,20454,19828],{},[22,20456,20459],{"className":20457,"code":20458,"language":27,"meta":28},[25],"主线程\n+\n1 个 Asio线程\n",[30,20460,20458],{"__ignoreMap":28},[15,20462,20463],{},"主线程通过：",[22,20465,20466],{"className":210,"code":16791,"language":212,"meta":28,"style":28},[30,20467,20468],{"__ignoreMap":28},[70,20469,20470,20472],{"class":72,"line":73},[70,20471,14251],{"class":76},[70,20473,3162],{"class":264},[15,20475,20476],{},"把串口相关任务交给唯一的 Asio 线程。",[15,20478,16507],{},[22,20480,20483],{"className":20481,"code":20482,"language":27,"meta":28},[25],"串口内部状态\n→ 只有一个线程真正操作\n→ 不需要 mutex\n→ 不需要 strand\n",[30,20484,20482],{"__ignoreMap":28},[15,20486,19896],{},[22,20488,20491],{"className":20489,"code":20490,"language":27,"meta":28},[25],"主线程\n+\n2 个 Asio线程\n",[30,20492,20490],{"__ignoreMap":28},[15,20494,20495],{},"两个 Asio 线程都执行：",[22,20497,20498],{"className":210,"code":2227,"language":212,"meta":28,"style":28},[30,20499,20500],{"__ignoreMap":28},[70,20501,20502,20504,20506],{"class":72,"line":73},[70,20503,2234],{"class":264},[70,20505,2237],{"class":76},[70,20507,2240],{"class":264},[15,20509,20510],{},"于是不同 handler 可能并发。",[15,20512,2160],{},[22,20514,20517],{"className":20515,"code":20516,"language":27,"meta":28},[25],"串口内部 handler\n↓\n统一进入 strand\n↓\n保证不并发\n",[30,20518,20516],{"__ignoreMap":28},[15,20520,20521],{},"整个学习过程可以记成：",[22,20523,20526],{"className":20524,"code":20525,"language":27,"meta":28},[25],"示例 7\n单线程\n↓\n完整异步收发类\n\n\n示例 8\n主线程 + 1 个 Asio线程\n↓\npost()\n↓\n线程间任务传递\n↓\n顺便理解 mutex 为什么会出现\n\n\n示例 9\n主线程 + 多个 Asio线程\n↓\nhandler 开始可能并发\n↓\nstrand\n↓\n串行化串口内部状态\n",[30,20527,20525],{"__ignoreMap":28},[15,20529,3227],{},[12,20531,20532],{},[15,20533,20534,20536,20537,20539,20540,20542,20543,20545],{},[30,20535,13542],{}," 解决的是“多个线程共同访问共享数据”；",[30,20538,16314],{}," 可以通过线程所有权设计减少这种共享；而当多个线程同时运行同一个 ",[30,20541,7856],{}," 时，",[30,20544,17256],{}," 可以进一步保证一组 Asio handler 不会彼此并发执行。",[43,20547,20549],{"id":20548},"standalone-asio","Standalone Asio",[15,20551,20552],{},"Standalone Asio ≈ 把 Boost.Asio 从 Boost 体系里单独拿出来，改用标准库类型。\n两者本质上是同一套 Asio 技术路线，作者和核心实现也基本同源；Standalone Asio 的代码会被周期性转换成 Boost.Asio。",[15,20554,20555,20556,20558,20559,20561,20562,20564],{},"一般来讲，boost库太大太重了，而且boost库里面很多内容比如",[30,20557,4546],{},"，",[30,20560,16865],{},"等早就被ISO C++收编到标准库了。\n咱们只需要用到boost里的asio的功能，所以在实际开发里，直接用",[30,20563,20549],{},"即可。",[15,20566,20567],{},"这俩没有任何性能差距，因为 Standalone Asio 和 Boost.Asio 本来就是同源实现，官方说明 Boost.Asio 是从 Asio 源码周期性转换而来的。",[3861,20569,20570,20582],{},[3864,20571,20572],{},[3867,20573,20574,20577,20579],{},[3870,20575,20576],{},"对比项",[3870,20578,20549],{},[3870,20580,20581],{},"Boost.Asio",[3880,20583,20584,20599,20614,20632,20645,20661,20677,20693,20707,20719,20729,20739,20750],{},[3867,20585,20586,20589,20594],{},[3885,20587,20588],{},"头文件",[3885,20590,20591],{},[30,20592,20593],{},"\u003Casio.hpp>",[3885,20595,20596],{},[30,20597,20598],{},"\u003Cboost\u002Fasio.hpp>",[3867,20600,20601,20604,20609],{},[3885,20602,20603],{},"命名空间",[3885,20605,20606],{},[30,20607,20608],{},"asio::",[3885,20610,20611],{},[30,20612,20613],{},"boost::asio::",[3867,20615,20616,20619,20627],{},[3885,20617,20618],{},"错误类型",[3885,20620,20621,3254,20624],{},[30,20622,20623],{},"std::error_code",[30,20625,20626],{},"asio::error_code",[3885,20628,20629],{},[30,20630,20631],{},"boost::system::error_code",[3867,20633,20634,20637,20642],{},[3885,20635,20636],{},"Boost 依赖",[3885,20638,20639],{},[924,20640,20641],{},"基本不需要",[3885,20643,20644],{},"属于 Boost，使用 Boost.System",[3867,20646,20647,20651,20656],{},[3885,20648,20649],{},[30,20650,7856],{},[3885,20652,20653],{},[30,20654,20655],{},"asio::io_context",[3885,20657,20658],{},[30,20659,20660],{},"boost::asio::io_context",[3867,20662,20663,20667,20672],{},[3885,20664,20665],{},[30,20666,5848],{},[3885,20668,20669],{},[30,20670,20671],{},"asio::serial_port",[3885,20673,20674],{},[30,20675,20676],{},"boost::asio::serial_port",[3867,20678,20679,20683,20688],{},[3885,20680,20681],{},[30,20682,17256],{},[3885,20684,20685],{},[30,20686,20687],{},"asio::strand",[3885,20689,20690],{},[30,20691,20692],{},"boost::asio::strand",[3867,20694,20695,20702,20705],{},[3885,20696,20697,3254,20699],{},[30,20698,14251],{},[30,20700,20701],{},"dispatch",[3885,20703,20704],{},"有",[3885,20706,20704],{},[3867,20708,20709,20715,20717],{},[3885,20710,20711,20712],{},"coroutine \u002F ",[30,20713,20714],{},"co_spawn",[3885,20716,20704],{},[3885,20718,20704],{},[3867,20720,20721,20724,20727],{},[3885,20722,20723],{},"性能",[3885,20725,20726],{},"基本相同",[3885,20728,20726],{},[3867,20730,20731,20734,20737],{},[3885,20732,20733],{},"API 风格",[3885,20735,20736],{},"几乎相同",[3885,20738,20736],{},[3867,20740,20741,20744,20747],{},[3885,20742,20743],{},"独立库发布",[3885,20745,20746],{},"是",[3885,20748,20749],{},"随 Boost 发布",[3867,20751,20752,20755,20760],{},[3885,20753,20754],{},"适合减少依赖",[3885,20756,20757],{},[924,20758,20759],{},"更好",[3885,20761,20762],{},"一般",[15,20764,20765],{},"代码对比：",[22,20767,20769],{"className":210,"code":20768,"language":212,"meta":28,"style":28},"#include \u003Cboost\u002Fasio.hpp>\n\nboost::asio::io_context io_context_;\nboost::asio::serial_port serial_port_{io_context_};\n\nboost::asio::post(io_context_, [this]() {\n    \u002F\u002F send\n});\n",[30,20770,20771,20777,20781,20792,20803,20807,20827,20832],{"__ignoreMap":28},[70,20772,20773,20775],{"class":72,"line":73},[70,20774,220],{"class":219},[70,20776,223],{"class":80},[70,20778,20779],{"class":72,"line":133},[70,20780,252],{"emptyLinePlaceholder":251},[70,20782,20783,20785,20787,20789],{"class":72,"line":141},[70,20784,540],{"class":76},[70,20786,386],{"class":264},[70,20788,389],{"class":76},[70,20790,20791],{"class":264},"::io_context io_context_;\n",[70,20793,20794,20796,20798,20800],{"class":72,"line":240},[70,20795,540],{"class":76},[70,20797,386],{"class":264},[70,20799,389],{"class":76},[70,20801,20802],{"class":264},"::serial_port serial_port_{io_context_};\n",[70,20804,20805],{"class":72,"line":248},[70,20806,252],{"emptyLinePlaceholder":251},[70,20808,20809,20811,20813,20815,20817,20819,20822,20824],{"class":72,"line":255},[70,20810,540],{"class":76},[70,20812,386],{"class":264},[70,20814,389],{"class":76},[70,20816,386],{"class":264},[70,20818,14251],{"class":76},[70,20820,20821],{"class":264},"(io_context_, [",[70,20823,11680],{"class":124},[70,20825,20826],{"class":264},"]() {\n",[70,20828,20829],{"class":72,"line":286},[70,20830,20831],{"class":295},"    \u002F\u002F send\n",[70,20833,20834],{"class":72,"line":292},[70,20835,20836],{"class":264},"});\n",[22,20838,20840],{"className":210,"code":20839,"language":212,"meta":28,"style":28},"#include \u003Casio.hpp>\n\nasio::io_context io_context_;\nasio::serial_port serial_port_{io_context_};\n\nasio::post(io_context_, [this]() {\n    \u002F\u002F send\n});\n",[30,20841,20842,20849,20853,20859,20865,20869,20883,20887],{"__ignoreMap":28},[70,20843,20844,20846],{"class":72,"line":73},[70,20845,220],{"class":219},[70,20847,20848],{"class":80}," \u003Casio.hpp>\n",[70,20850,20851],{"class":72,"line":133},[70,20852,252],{"emptyLinePlaceholder":251},[70,20854,20855,20857],{"class":72,"line":141},[70,20856,389],{"class":76},[70,20858,20791],{"class":264},[70,20860,20861,20863],{"class":72,"line":240},[70,20862,389],{"class":76},[70,20864,20802],{"class":264},[70,20866,20867],{"class":72,"line":248},[70,20868,252],{"emptyLinePlaceholder":251},[70,20870,20871,20873,20875,20877,20879,20881],{"class":72,"line":255},[70,20872,389],{"class":76},[70,20874,386],{"class":264},[70,20876,14251],{"class":76},[70,20878,20821],{"class":264},[70,20880,11680],{"class":124},[70,20882,20826],{"class":264},[70,20884,20885],{"class":72,"line":286},[70,20886,20831],{"class":295},[70,20888,20889],{"class":72,"line":292},[70,20890,20836],{"class":264},[15,20892,20893],{},"错误处理：",[15,20895,20896,20897,20900,20901,20904,20905,20907],{},"从",[30,20898,20899],{},"boost::system::error_code ec;","换成",[30,20902,20903],{},"asio::error_code ec;","或者",[30,20906,20623],{},"（更建议用标准库，实际上就是boost库被收编的内容）",[15,20909,20910],{},"然后在版本上，拿Ubuntu 22.04 Jammy举例子：",[15,20912,20913,20915,20916,20919,20920,20915,20923,20926,20927,20915,20929,38],{},[30,20914,20549],{},"的版本是",[30,20917,20918],{},"libasio-dev = 1.18.1","。\n",[30,20921,20922],{},"Boost",[30,20924,20925],{},"libboost-dev  1.74",",但里面的",[30,20928,20581],{},[30,20930,20931],{},"Asio 1.18.0",[15,20933,20934],{},"所以几乎就是同一代，几乎没有任何差距。",[15,20936,20937],{},"其他的全部可以原封不动保留。",[20939,20940,20941],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":28,"searchDepth":133,"depth":133,"links":20943},[20944,20948,20957,20972,20981,20995,21008,21020,21036,21045,21064,21081],{"id":45,"depth":133,"text":46,"children":20945},[20946,20947],{"id":57,"depth":141,"text":58},{"id":109,"depth":141,"text":109},{"id":178,"depth":133,"text":20949,"children":20950},"示例 1：普通 main() 里同步打开串口并发送一行",[20951,20952,20953,20954,20955,20956],{"id":186,"depth":141,"text":186},{"id":207,"depth":141,"text":207},{"id":930,"depth":141,"text":930},{"id":982,"depth":141,"text":982},{"id":1016,"depth":141,"text":1016},{"id":1026,"depth":141,"text":1026},{"id":1098,"depth":133,"text":20958,"children":20959},"示例 2：普通 main() 里同步读取串口数据",[20960,20961,20962,20963,20964,20965,20967,20969,20971],{"id":1105,"depth":141,"text":186},{"id":1144,"depth":141,"text":207},{"id":1900,"depth":141,"text":930},{"id":1991,"depth":141,"text":982},{"id":2125,"depth":141,"text":1016},{"id":2243,"depth":141,"text":20966},"如果实际收到的数据远远超过 11 个字节，会不会把 array 撑爆？",{"id":2422,"depth":141,"text":20968},"下一次读取时，会从 array 的哪里开始写？",{"id":2616,"depth":141,"text":20970},"如果剩余数据不够填满整个 array 呢？",{"id":2726,"depth":141,"text":1026},{"id":3243,"depth":133,"text":20973,"children":20974},"some()相关的读取函数（不常用）",[20975,20977,20978,20980],{"id":3250,"depth":141,"text":20976},"read() \u002F write() 和 read_some() \u002F write_some() 的区别",{"id":3858,"depth":141,"text":3859},{"id":3948,"depth":141,"text":20979},"为什么 read() \u002F write() 不是 serial 的成员函数？",{"id":4257,"depth":141,"text":4258},{"id":4394,"depth":133,"text":20982,"children":20983},"示例 3：普通 main() 里异步发送串口数据",[20984,20985,20986,20987,20988,20989,20991,20993],{"id":4401,"depth":141,"text":186},{"id":4476,"depth":141,"text":207},{"id":5286,"depth":141,"text":930},{"id":5337,"depth":141,"text":982},{"id":5419,"depth":141,"text":1016},{"id":5533,"depth":141,"text":20990},"async_write() 的回调参数",{"id":5697,"depth":141,"text":20992},"为什么 msg 不能过早销毁？",{"id":5952,"depth":141,"text":20994},"boost::asio::async_write() 说明",{"id":6032,"depth":133,"text":20996,"children":20997},"示例 4：普通 main() 里异步读取串口数据",[20998,20999,21000,21001,21002,21003,21005,21006],{"id":6039,"depth":141,"text":186},{"id":6129,"depth":141,"text":207},{"id":7004,"depth":141,"text":930},{"id":7079,"depth":141,"text":982},{"id":7126,"depth":141,"text":1016},{"id":7306,"depth":141,"text":21004},"为什么把 &buffer 额外传给回调？（很重要，要记得）",{"id":7466,"depth":141,"text":7467},{"id":7541,"depth":141,"text":21007},"boost::asio::async_read() 说明",{"id":7644,"depth":133,"text":7645,"children":21009},[21010,21011,21012,21013,21014,21016,21017,21018,21019],{"id":7648,"depth":141,"text":186},{"id":7773,"depth":141,"text":207},{"id":9010,"depth":141,"text":930},{"id":9055,"depth":141,"text":982},{"id":9085,"depth":141,"text":21015},"第一次调用 async_send() 时发生了什么？",{"id":9235,"depth":141,"text":9236},{"id":9322,"depth":141,"text":9323},{"id":9440,"depth":141,"text":9441},{"id":9592,"depth":141,"text":9593},{"id":9650,"depth":133,"text":9651,"children":21021},[21022,21023,21024,21025,21026,21027,21029,21031,21033,21035],{"id":9654,"depth":141,"text":186},{"id":9767,"depth":141,"text":207},{"id":10727,"depth":141,"text":930},{"id":10813,"depth":141,"text":982},{"id":10886,"depth":141,"text":10887},{"id":11033,"depth":141,"text":21028},"为什么 serial_ 和 buffer_ 要做成成员变量？",{"id":11284,"depth":141,"text":21030},"为什么下一次读取会覆盖上一次的 buffer_？",{"id":11495,"depth":141,"text":21032},"为什么这里不会出现两个读取同时修改 buffer_？",{"id":11563,"depth":141,"text":21034},"成员函数的 std::bind",{"id":11701,"depth":141,"text":11702},{"id":11740,"depth":133,"text":11741,"children":21037},[21038,21039,21040,21041,21042,21044],{"id":11744,"depth":141,"text":186},{"id":11789,"depth":141,"text":207},{"id":13304,"depth":141,"text":930},{"id":13397,"depth":141,"text":13397},{"id":13538,"depth":141,"text":21043},"为什么这里不需要 mutex？",{"id":13659,"depth":141,"text":13659},{"id":13689,"depth":133,"text":13690,"children":21046},[21047,21048,21049,21050,21051,21053,21055,21057,21059,21061,21063],{"id":13696,"depth":141,"text":186},{"id":13761,"depth":141,"text":207},{"id":16139,"depth":141,"text":930},{"id":16248,"depth":141,"text":16248},{"id":16310,"depth":141,"text":21052},"为什么要使用 post()？",{"id":16402,"depth":141,"text":21054},"如果直接共享 write_queue_，就需要 mutex",{"id":16541,"depth":141,"text":21056},"但本例为什么没有使用 mutex？",{"id":16686,"depth":141,"text":21058},"post() 可以理解成什么？",{"id":16813,"depth":141,"text":21060},"work_guard 在这里为什么特别重要？",{"id":17017,"depth":141,"text":21062},"为什么结束时先 stop()，再 guard.reset()？",{"id":17187,"depth":141,"text":17188},{"id":17249,"depth":133,"text":21065,"children":21066},"示例 9：多个线程同时运行 io.run()，使用 strand 避免 handler 并发",[21067,21068,21069,21070,21072,21074,21076,21078,21080],{"id":17263,"depth":141,"text":186},{"id":17368,"depth":141,"text":207},{"id":19759,"depth":141,"text":930},{"id":19821,"depth":141,"text":21071},"为什么示例 8 不需要 strand，示例 9 却需要？",{"id":19934,"depth":141,"text":21073},"strand 在这里发挥什么作用？",{"id":20119,"depth":141,"text":21075},"strand 不是把串口固定到某一个线程",{"id":20188,"depth":141,"text":21077},"为什么不仅 on_read() \u002F on_write() 要绑定 strand？",{"id":20337,"depth":141,"text":21079},"那这里能不能不用 strand，改用 mutex？",{"id":20451,"depth":141,"text":20452},{"id":20548,"depth":133,"text":20549},"2100-0100-0300","2023-10-05","2023-10-05-cplusplus-jiao-xue","\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue","Cplusplus教学","md",false,{},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0300-chuan-kou-tong-xin",{"title":5,"description":28},"wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0300-串口通信","tcPKqXPxwTHQcl490yPANZ08ck8yS8MtxUdrUd58hrM",[21095,21102,21108,21114,21120,21126,21132,21138,21144,21150,21156,21162,21168,21174,21179,21185,21191,21197,21203,21209,21215,21221,21227,21233,21239,21245,21251,21257,21263,21269,21275,21281,21287,21293,21299,21305,21311,21317,21323,21329,21334,21340,21346,21352,21358,21364,21370,21376,21382,21388,21394,21400,21405,21411,21417,21423,21429,21435,21441,21447,21453,21459,21465,21471,21477,21483,21489,21495,21501,21507,21513,21519,21525,21531,21537,21539,21545,21551,21557,21563,21569,21575,21581,21587,21593,21599,21605,21611,21617,21623,21629,21635],{"path":21096,"stem":21097,"title":21098,"authors":21099,"date":21083,"chapterOrder":21100,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0100-c-kai-fa-huan-jing-da-jian-yu-ce-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F0100-C++开发环境搭建与测试","C++开发环境搭建与测试",[7],"0100",0,{"path":21103,"stem":21104,"title":21105,"authors":21106,"date":21083,"chapterOrder":21107,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0200-c-ji-chu-chu-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F0200-C++基础初识","C++基础初识",[7],"0200",{"path":21109,"stem":21110,"title":21111,"authors":21112,"date":21083,"chapterOrder":21113,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0300-shu-ju-lei-xing-yu-shu-ju-cun-fang","wiki\u002F2023-10-05-Cplusplus教学\u002F0300-数据类型与数据存放","数据类型与数据存放",[7],"0300",{"path":21115,"stem":21116,"title":21117,"authors":21118,"date":21083,"chapterOrder":21119,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0400-shu-ru-shu-chu","wiki\u002F2023-10-05-Cplusplus教学\u002F0400-输入输出","输入输出",[7],"0400",{"path":21121,"stem":21122,"title":21123,"authors":21124,"date":21083,"chapterOrder":21125,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0500-yun-suan-fu","wiki\u002F2023-10-05-Cplusplus教学\u002F0500-运算符","运算符",[7],"0500",{"path":21127,"stem":21128,"title":21129,"authors":21130,"date":21083,"chapterOrder":21131,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0600-cheng-xu-liu-cheng-jie-gou","wiki\u002F2023-10-05-Cplusplus教学\u002F0600-程序流程结构","程序流程结构",[7],"0600",{"path":21133,"stem":21134,"title":21135,"authors":21136,"date":21083,"chapterOrder":21137,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0700-shu-zu","wiki\u002F2023-10-05-Cplusplus教学\u002F0700-数组","数组",[7],"0700",{"path":21139,"stem":21140,"title":21141,"authors":21142,"date":21083,"chapterOrder":21143,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0800-han-shu-yu-tou-wen-jian","wiki\u002F2023-10-05-Cplusplus教学\u002F0800-函数与头文件","函数与头文件",[7],"0800",{"path":21145,"stem":21146,"title":21147,"authors":21148,"date":21083,"chapterOrder":21149,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0900-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F0900-指针","指针",[7],"0900",{"path":21151,"stem":21152,"title":21153,"authors":21154,"date":21083,"chapterOrder":21155,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1000-jie-gou-ti-yu-gong-yong-ti","wiki\u002F2023-10-05-Cplusplus教学\u002F1000-结构体与共用体","结构体与共用体",[7],"1000",{"path":21157,"stem":21158,"title":21159,"authors":21160,"date":21083,"chapterOrder":21161,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1100-nei-cun-fen-qu-yu-sheng-ming-zhou-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1100-内存分区与生命周期","内存分区与生命周期",[7],"1100",{"path":21163,"stem":21164,"title":21165,"authors":21166,"date":21083,"chapterOrder":21167,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1200-yin-yong","wiki\u002F2023-10-05-Cplusplus教学\u002F1200-引用","引用",[7],"1200",{"path":21169,"stem":21170,"title":21171,"authors":21172,"date":21083,"chapterOrder":21173,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1300-han-shu-ti-gao","wiki\u002F2023-10-05-Cplusplus教学\u002F1300-函数提高","函数提高",[7],"1300",{"path":21175,"stem":21176,"title":20603,"authors":21177,"date":21083,"chapterOrder":21178,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1350-ming-ming-kong-jian","wiki\u002F2023-10-05-Cplusplus教学\u002F1350-命名空间",[7],"1350",{"path":21180,"stem":21181,"title":21182,"authors":21183,"date":21083,"chapterOrder":21184,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0100-feng-zhuang","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0100-封装","封装",[7],"1400-0100",{"path":21186,"stem":21187,"title":21188,"authors":21189,"date":21083,"chapterOrder":21190,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0200-dui-xiang-chu-shi-hua-he-qing-li","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0200-对象初始化和清理","对象初始化和清理",[7],"1400-0200",{"path":21192,"stem":21193,"title":21194,"authors":21195,"date":21083,"chapterOrder":21196,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0300-dui-xiang-mo-xing-yu-this-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0300-对象模型与this指针","对象模型与this指针",[7],"1400-0300",{"path":21198,"stem":21199,"title":21200,"authors":21201,"date":21083,"chapterOrder":21202,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0400-you-yuan-yu-yun-suan-fu-zhong-zai","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0400-友元与运算符重载","友元与运算符重载",[7],"1400-0400",{"path":21204,"stem":21205,"title":21206,"authors":21207,"date":21083,"chapterOrder":21208,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0500-ji-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0500-继承","继承",[7],"1400-0500",{"path":21210,"stem":21211,"title":21212,"authors":21213,"date":21083,"chapterOrder":21214,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0600-duo-tai","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0600-多态","多态",[7],"1400-0600",{"path":21216,"stem":21217,"title":21218,"authors":21219,"date":21083,"chapterOrder":21220,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-lei-he-dui-xiang","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-类和对象","类和对象",[7],"1400",{"path":21222,"stem":21223,"title":21224,"authors":21225,"date":21083,"chapterOrder":21226,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1450-han-shu-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F1450-函数指针","函数指针",[7],"1450",{"path":21228,"stem":21229,"title":21230,"authors":21231,"date":21083,"chapterOrder":21232,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1500-wen-jian-cao-zuo","wiki\u002F2023-10-05-Cplusplus教学\u002F1500-文件操作","文件操作",[7],"1500",{"path":21234,"stem":21235,"title":21236,"authors":21237,"date":21083,"chapterOrder":21238,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1600-yi-chang-chu-li-yu-cuo-wu-ma","wiki\u002F2023-10-05-Cplusplus教学\u002F1600-异常处理与错误码","异常处理",[7],"1600",{"path":21240,"stem":21241,"title":21242,"authors":21243,"date":21083,"chapterOrder":21244,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1700-mu-ban","wiki\u002F2023-10-05-Cplusplus教学\u002F1700-模板","模板",[7],"1700",{"path":21246,"stem":21247,"title":21248,"authors":21249,"date":21083,"chapterOrder":21250,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0100-stl-chu-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0100-STL初识","STL初识",[7],"1800-0100",{"path":21252,"stem":21253,"title":21254,"authors":21255,"date":21083,"chapterOrder":21256,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0200-std-array","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0200-std-array","std::array",[7],"1800-0200",{"path":21258,"stem":21259,"title":21260,"authors":21261,"date":21083,"chapterOrder":21262,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0300-string-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0300-string容器","string容器",[7],"1800-0300",{"path":21264,"stem":21265,"title":21266,"authors":21267,"date":21083,"chapterOrder":21268,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0400-vector-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0400-vector容器","vector 容器",[7],"1800-0400",{"path":21270,"stem":21271,"title":21272,"authors":21273,"date":21083,"chapterOrder":21274,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0500-deque-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0500-deque容器","deque 容器",[7],"1800-0500",{"path":21276,"stem":21277,"title":21278,"authors":21279,"date":21083,"chapterOrder":21280,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0600-stack-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0600-stack容器","stack 容器",[7],"1800-0600",{"path":21282,"stem":21283,"title":21284,"authors":21285,"date":21083,"chapterOrder":21286,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0700-queue-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0700-queue容器","queue 容器",[7],"1800-0700",{"path":21288,"stem":21289,"title":21290,"authors":21291,"date":21083,"chapterOrder":21292,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0800-list-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0800-list容器","list 容器",[7],"1800-0800",{"path":21294,"stem":21295,"title":21296,"authors":21297,"date":21083,"chapterOrder":21298,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0900-set-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0900-set容器","set \u002F multiset 容器",[7],"1800-0900",{"path":21300,"stem":21301,"title":21302,"authors":21303,"date":21083,"chapterOrder":21304,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1000-map-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1000-map容器","map \u002F multimap 容器",[7],"1800-1000",{"path":21306,"stem":21307,"title":21308,"authors":21309,"date":21083,"chapterOrder":21310,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1100-han-shu-dui-xiang-yu-wei-ci","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1100-函数对象与谓词","函数对象与谓词",[7],"1800-1100",{"path":21312,"stem":21313,"title":21314,"authors":21315,"date":21083,"chapterOrder":21316,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1200-chang-yong-suan-fa","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1200-常用算法","常用算法",[7],"1800-1200",{"path":21318,"stem":21319,"title":21320,"authors":21321,"date":21083,"chapterOrder":21322,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-stl-ti-gao-bian-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-STL提高编程","STL提高编程",[7],"1800",{"path":21324,"stem":21325,"title":21326,"authors":21327,"date":21083,"chapterOrder":21328,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1900-c-lei-xing-zhuan-huan","wiki\u002F2023-10-05-Cplusplus教学\u002F1900-C++类型转换","C++类型转换",[7],"1900",{"path":21330,"stem":21331,"title":16830,"authors":21332,"date":21083,"chapterOrder":21333,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0100-auto","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0100-auto",[7],"2000-0100",{"path":21335,"stem":21336,"title":21337,"authors":21338,"date":21083,"chapterOrder":21339,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0200-nullptr","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0200-nullptr","nullptr",[7],"2000-0200",{"path":21341,"stem":21342,"title":21343,"authors":21344,"date":21083,"chapterOrder":21345,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0300-using","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0300-using","using",[7],"2000-0300",{"path":21347,"stem":21348,"title":21349,"authors":21350,"date":21083,"chapterOrder":21351,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0400-enum-class","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0400-enum-class","enum class",[7],"2000-0400",{"path":21353,"stem":21354,"title":21355,"authors":21356,"date":21083,"chapterOrder":21357,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0500-fan-wei-for-xun-huan","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0500-范围for循环","范围 for 循环",[7],"2000-0500",{"path":21359,"stem":21360,"title":21361,"authors":21362,"date":21083,"chapterOrder":21363,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0600-jie-gou-hua-bang-ding","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0600-结构化绑定","结构化绑定",[7],"2000-0600",{"path":21365,"stem":21366,"title":21367,"authors":21368,"date":21083,"chapterOrder":21369,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0700-constexpr","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0700-constexpr","constexpr",[7],"2000-0700",{"path":21371,"stem":21372,"title":21373,"authors":21374,"date":21083,"chapterOrder":21375,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0800-raii","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0800-RAII","RAII",[7],"2000-0800",{"path":21377,"stem":21378,"title":21379,"authors":21380,"date":21083,"chapterOrder":21381,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0900-zhi-neng-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0900-智能指针","智能指针",[7],"2000-0900",{"path":21383,"stem":21384,"title":21385,"authors":21386,"date":21083,"chapterOrder":21387,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1000-you-zhi-yin-yong-he-yi-dong-yu-yi","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1000-右值引用和移动语义","右值引用和移动语义",[7],"2000-1000",{"path":21389,"stem":21390,"title":21391,"authors":21392,"date":21083,"chapterOrder":21393,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1100-lambda-biao-da-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1100-Lambda表达式","Lambda 表达式",[7],"2000-1100",{"path":21395,"stem":21396,"title":21397,"authors":21398,"date":21083,"chapterOrder":21399,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1200-std-function","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1200-std-function","std::function",[7],"2000-1200",{"path":21401,"stem":21402,"title":37,"authors":21403,"date":21083,"chapterOrder":21404,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1300-std-bind","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1300-std-bind",[7],"2000-1300",{"path":21406,"stem":21407,"title":21408,"authors":21409,"date":21083,"chapterOrder":21410,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1400-std-optional","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1400-std-optional","std::optional",[7],"2000-1400",{"path":21412,"stem":21413,"title":21414,"authors":21415,"date":21083,"chapterOrder":21416,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1500-std-variant","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1500-std-variant","std::variant",[7],"2000-1500",{"path":21418,"stem":21419,"title":21420,"authors":21421,"date":21083,"chapterOrder":21422,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1600-std-span","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1600-std-span","std::span",[7],"2000-1600",{"path":21424,"stem":21425,"title":21426,"authors":21427,"date":21083,"chapterOrder":21428,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1700-std-format-print","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1700-std-format-print","std::format \u002F std::print",[7],"2000-1700",{"path":21430,"stem":21431,"title":21432,"authors":21433,"date":21083,"chapterOrder":21434,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1800-std-chrono","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1800-std-chrono","std::chrono",[7],"2000-1800",{"path":21436,"stem":21437,"title":21438,"authors":21439,"date":21083,"chapterOrder":21440,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0100-bing-fa-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0100-并发是什么","并发是什么",[7],"2000-1900-0100",{"path":21442,"stem":21443,"title":21444,"authors":21445,"date":21083,"chapterOrder":21446,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0200-bing-xing-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0200-并行是什么","并行是什么",[7],"2000-1900-0200",{"path":21448,"stem":21449,"title":21450,"authors":21451,"date":21083,"chapterOrder":21452,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0300-xie-cheng-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0300-协程是什么","协程是什么",[7],"2000-1900-0300",{"path":21454,"stem":21455,"title":21456,"authors":21457,"date":21083,"chapterOrder":21458,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1000-bing-fa-bian-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1000-并发编程","并发编程",[7],"2000-1900-1000",{"path":21460,"stem":21461,"title":21462,"authors":21463,"date":21083,"chapterOrder":21464,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1100-std-thread","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1100-std-thread","std::thread",[7],"2000-1900-1100",{"path":21466,"stem":21467,"title":21468,"authors":21469,"date":21083,"chapterOrder":21470,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1200-mutex-lock-guard","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1200-mutex-lock-guard","mutex 与 RAII 锁",[7],"2000-1900-1200",{"path":21472,"stem":21473,"title":21474,"authors":21475,"date":21083,"chapterOrder":21476,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1300-std-atomic","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1300-std-atomic","std::atomic",[7],"2000-1900-1300",{"path":21478,"stem":21479,"title":21480,"authors":21481,"date":21083,"chapterOrder":21482,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1400-condition-variable","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1400-condition-variable","condition_variable",[7],"2000-1900-1400",{"path":21484,"stem":21485,"title":21486,"authors":21487,"date":21083,"chapterOrder":21488,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1500-future-async-promise","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1500-future-async-promise","future、async、promise 与 packaged_task",[7],"2000-1900-1500",{"path":21490,"stem":21491,"title":21492,"authors":21493,"date":21083,"chapterOrder":21494,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1600-jthread-stop-token","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1600-jthread-stop-token","jthread 与 stop_token",[7],"2000-1900-1600",{"path":21496,"stem":21497,"title":21498,"authors":21499,"date":21083,"chapterOrder":21500,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1700-semaphore-latch-barrier","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1700-semaphore-latch-barrier","semaphore、latch 与 barrier",[7],"2000-1900-1700",{"path":21502,"stem":21503,"title":21504,"authors":21505,"date":21083,"chapterOrder":21506,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-bing-fa-bing-xing-yu-xie-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-并发并行与协程","并发、并行与协程",[7],"2000-1900",{"path":21508,"stem":21509,"title":21510,"authors":21511,"date":21083,"chapterOrder":21512,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-2000-std-filesystem","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-2000-std-filesystem","std::filesystem",[7],"2000-2000",{"path":21514,"stem":21515,"title":21516,"authors":21517,"date":21083,"chapterOrder":21518,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-2100-modules-jian-jie","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-2100-modules简介","modules 简介",[7],"2000-2100",{"path":21520,"stem":21521,"title":21522,"authors":21523,"date":21083,"chapterOrder":21524,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-xian-dai-c","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-现代C++","现代C++",[7],"2000",{"path":21526,"stem":21527,"title":21528,"authors":21529,"date":21083,"chapterOrder":21530,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0100-ding-shi-qi-yu-yi-bu-io","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0100-定时器与异步IO","定时器与异步 IO",[7],"2100-0100-0100",{"path":21532,"stem":21533,"title":21534,"authors":21535,"date":21083,"chapterOrder":21536,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0200-boost-asio-ji-chu","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0200-Boost.Asio基础","Boost.Asio 基础",[7],"2100-0100-0200",{"path":21090,"stem":21092,"title":5,"authors":21538,"date":21083,"chapterOrder":21082,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},[7],{"path":21540,"stem":21541,"title":21542,"authors":21543,"date":21083,"chapterOrder":21544,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0350-chuan-kou-tong-xin-chuan-kou-bao-xie-yi-shi-li","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0350-串口通信串口包协议实例","串口通信串口包协议实例",[7],"2100-0100-0350",{"path":21546,"stem":21547,"title":21548,"authors":21549,"date":21083,"chapterOrder":21550,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0400-tcp-tong-xin","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0400-TCP通信","TCP 通信",[7],"2100-0100-0400",{"path":21552,"stem":21553,"title":21554,"authors":21555,"date":21083,"chapterOrder":21556,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0500-udp-tong-xin","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0500-UDP通信","UDP 通信",[7],"2100-0100-0500",{"path":21558,"stem":21559,"title":21560,"authors":21561,"date":21083,"chapterOrder":21562,"chapterDepth":133,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0600-ji-qi-ren-gong-cheng-xie-fa-yu-ros2-ji-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0600-机器人工程写法与ROS2集成","机器人工程写法与 ROS2 集成",[7],"2100-0100-0600",{"path":21564,"stem":21565,"title":21566,"authors":21567,"date":21083,"chapterOrder":21568,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-boost-asio-yi-bu-io-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-Boost.Asio异步IO库","Boost.Asio异步IO库",[7],"2100-0100",{"path":21570,"stem":21571,"title":21572,"authors":21573,"date":21083,"chapterOrder":21574,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0200-eigen-xian-xing-dai-shu-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0200-Eigen线性代数库","Eigen线性代数库",[7],"2100-0200",{"path":21576,"stem":21577,"title":21578,"authors":21579,"date":21083,"chapterOrder":21580,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0300-opencv-ji-suan-ji-shi-jue-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0300-OpenCV计算机视觉库","OpenCV计算机视觉库",[7],"2100-0300",{"path":21582,"stem":21583,"title":21584,"authors":21585,"date":21083,"chapterOrder":21586,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0400-pcl-dian-yun-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0400-PCL点云库","PCL点云库",[7],"2100-0400",{"path":21588,"stem":21589,"title":21590,"authors":21591,"date":21083,"chapterOrder":21592,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0500-sophus-li-qun-li-dai-shu-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0500-Sophus李群李代数库","Sophus 李群李代数库",[7],"2100-0500",{"path":21594,"stem":21595,"title":21596,"authors":21597,"date":21083,"chapterOrder":21598,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-chang-yong-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-常用库","常用库学习",[7],"2100",{"path":21600,"stem":21601,"title":21602,"authors":21603,"date":21083,"chapterOrder":21604,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0100-cmakepresets-yu-gou-jian-an-zhuang","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0100-CMakePresets与构建安装","CMakePresets与构建安装",[7],"2200-0100",{"path":21606,"stem":21607,"title":21608,"authors":21609,"date":21083,"chapterOrder":21610,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0200-ding-ceng-cmake-yu-gong-gong-bian-yi-xuan-xiang","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0200-顶层CMake与公共编译选项","顶层CMake与公共编译选项",[7],"2200-0200",{"path":21612,"stem":21613,"title":21614,"authors":21615,"date":21083,"chapterOrder":21616,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0300-src-yu-lib-mo-kuai-cmake-xiang-jie","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0300-src与lib模块CMake详解","src与lib模块CMake详解",[7],"2200-0300",{"path":21618,"stem":21619,"title":21620,"authors":21621,"date":21083,"chapterOrder":21622,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0400-di-san-fang-ku-yi-lai-xie-fa","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0400-第三方库依赖写法","第三方库依赖写法",[7],"2200-0400",{"path":21624,"stem":21625,"title":21626,"authors":21627,"date":21083,"chapterOrder":21628,"chapterDepth":73,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0500-mu-ban-kuo-zhan-yu-chang-jian-wen-ti","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0500-模板扩展与常见问题","模板扩展与常见问题",[7],"2200-0500",{"path":21630,"stem":21631,"title":21632,"authors":21633,"date":21083,"chapterOrder":21634,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":21088},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-cmake-gong-cheng-mu-ban","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-CMake工程模板","CMake工程模板",[7],"2200",{"path":21085,"stem":21636,"title":21637,"authors":21638,"date":21083,"chapterOrder":21639,"chapterDepth":21101,"docKey":21084,"docRoot":21085,"docTitle":21086,"isWikiDoc":251,"isWikiIndex":251},"wiki\u002F2023-10-05-Cplusplus教学\u002Findex","C\u002FC++教程",[7],null,[21641,21643,21646,21649],{"name":7,"image":21642},"\u002Fimages\u002Fmember_photo\u002F董佳辉.jpg",{"name":21644,"image":21645},"宫金良","\u002Fimages\u002Fmember_photo\u002F宫金良.jpg",{"name":21647,"image":21648},"巩丽","\u002Fimages\u002Fmember_photo\u002F巩丽.png",{"name":21650,"image":21651},"张彦斐","\u002Fimages\u002Fmember_photo\u002F张彦斐.jpg",1792431899756]