Skip to content

Commit b67d878

Browse files
author
zhengshuxin
committed
Site updated: 2023-02-05 11:46:19
1 parent b54fc1c commit b67d878

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

2019/04/07/fiber/index.html

+10-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<meta property="og:description" content="Acl 网络协程框架编程指南 摘要 一、概述 二、简单示例 三、编译安装 四、使用多核 五、多核同步 六、消息传递 七、HOOK API 八、域名解析 九、协程共享栈 十、使第三方网络库协程化 十一、Windows 界面编程协程化 十二、打印协程调用栈 十三、检测协程死锁问题 摘要本文主要讲述Acl网络协程框架的使用,从协程的应用场景出发,以一个简单的协程示例开始,然后逐步深入到Acl网">
2525
<meta property="og:locale" content="zh_CN">
2626
<meta property="article:published_time" content="2019-04-07T05:08:24.000Z">
27-
<meta property="article:modified_time" content="2023-02-05T03:08:24.697Z">
27+
<meta property="article:modified_time" content="2023-02-05T03:46:11.645Z">
2828
<meta property="article:author" content="zsxxsz">
2929
<meta property="article:tag" content="协程编程">
3030
<meta name="twitter:card" content="summary_large_image">
@@ -237,7 +237,7 @@
237237
<span class="post-meta mr-2">
238238
<i class="iconfont icon-chart"></i>
239239

240-
31k
240+
32k
241241

242242
</span>
243243

@@ -248,7 +248,7 @@
248248

249249

250250

251-
259 分钟
251+
264 分钟
252252

253253
</span>
254254

@@ -325,6 +325,13 @@ <h2 id="二、简单示例"><a href="#二、简单示例" class="headerlink" tit
325325
<p><strong>协程调度其实是应用层面多个协程之间通过上下文切换形成的协作过程,如果一个协程库仅是实现了上下文切换,其实并不具备太多实用价值,当与网络事件绑定后,其价值才会显现出来</strong>。下面一个简单的使用协程的网络服务程序:</p>
326326
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;acl-lib/acl_cpp/lib_acl.hpp&gt;</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;acl-lib/fiber/libfiber.hpp&gt;</span></span><br><br><span class="hljs-comment">// 客户端协程处理类,用来回显客户发送的内容,每一个客户端连接绑定一个独立的协程</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">fiber_echo</span> : <span class="hljs-keyword">public</span> acl::fiber &#123;<br><span class="hljs-keyword">public</span>:<br> <span class="hljs-built_in">fiber_echo</span>(acl::socket_stream* conn) : <span class="hljs-built_in">conn_</span>(conn) &#123;&#125;<br><br><span class="hljs-keyword">private</span>:<br> acl::socket_stream* conn_;<br> ~<span class="hljs-built_in">fiber_echo</span>(<span class="hljs-type">void</span>) &#123; <span class="hljs-keyword">delete</span> conn_; &#125;<br><br><span class="hljs-keyword">private</span>:<br> <span class="hljs-comment">// @override</span><br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">run</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> </span>&#123;<br> <span class="hljs-type">char</span> buf[<span class="hljs-number">8192</span>];<br> <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br> <span class="hljs-comment">// 从客户端读取数据(第三个参数为false表示不必填满整个缓冲区才返回)</span><br> <span class="hljs-type">int</span> ret = conn_-&gt;<span class="hljs-built_in">read</span>(buf, <span class="hljs-built_in">sizeof</span>(buf), <span class="hljs-literal">false</span>);<br> <span class="hljs-keyword">if</span> (ret == <span class="hljs-number">-1</span>) &#123;<br> <span class="hljs-keyword">break</span>;<br> &#125;<br> <span class="hljs-comment">// 向客户端写入读到的数据</span><br> <span class="hljs-keyword">if</span> (conn_-&gt;<span class="hljs-built_in">write</span>(buf, ret) != ret) &#123;<br> <span class="hljs-keyword">break</span>;<br> &#125;<br> &#125;<br> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>; <span class="hljs-comment">// 自销毁动态创建的协程对象</span><br> &#125;<br>&#125;;<br><br><span class="hljs-comment">// 独立的协程过程,接收客户端连接,并将接收的连接与新创建的协程进行绑定</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">fiber_listen</span> : <span class="hljs-keyword">public</span> acl::fiber &#123;<br><span class="hljs-keyword">public</span>:<br> <span class="hljs-built_in">fiber_listen</span>(acl::server_socket&amp; listener) : <span class="hljs-built_in">listener_</span>(listener) &#123;&#125;<br><br><span class="hljs-keyword">private</span>:<br> acl::server_socket&amp; listener_;<br> ~<span class="hljs-built_in">fiber_listen</span>(<span class="hljs-type">void</span>) &#123;&#125;<br><br><span class="hljs-keyword">private</span>:<br> <span class="hljs-comment">// @override</span><br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">run</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> </span>&#123;<br> <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br> acl::socket_stream* conn = listener_.<span class="hljs-built_in">accept</span>(); <span class="hljs-comment">// 等待客户端连接</span><br> <span class="hljs-keyword">if</span> (conn == <span class="hljs-literal">NULL</span>) &#123;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;accept failed: %s\r\n&quot;</span>, acl::<span class="hljs-built_in">last_serror</span>());<br> <span class="hljs-keyword">break</span>;<br> &#125;<br> <span class="hljs-comment">// 创建并启动单独的协程处理客户端连接</span><br> acl::fiber* fb = <span class="hljs-keyword">new</span> <span class="hljs-built_in">fiber_echo</span>(conn);<br> <span class="hljs-comment">// 启动独立的客户端处理协程</span><br> fb-&gt;<span class="hljs-built_in">start</span>();<br> &#125;<br> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>;<br> &#125;<br>&#125;;<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> </span>&#123;<br> <span class="hljs-type">const</span> <span class="hljs-type">char</span>* addr = <span class="hljs-string">&quot;127.0.0.1:8800&quot;</span>;<br> acl::server_socket listener;<br> <span class="hljs-comment">// 监听本地地址</span><br> <span class="hljs-keyword">if</span> (listener.<span class="hljs-built_in">open</span>(addr) == <span class="hljs-literal">false</span>) &#123;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;listen %s error %s\r\n&quot;</span>, addr, acl::<span class="hljs-built_in">last_serror</span>());<br> <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br> &#125;<br><br> <span class="hljs-comment">// 创建并启动独立的监听协程,接受客户端连接</span><br> acl::fiber* fb = <span class="hljs-keyword">new</span> <span class="hljs-built_in">fiber_listen</span>(listener);<br> fb-&gt;<span class="hljs-built_in">start</span>();<br><br> <span class="hljs-comment">// 启动协程调度器</span><br> acl::fiber::<span class="hljs-built_in">schedule</span>();<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>&#125;<br></code></pre></td></tr></table></figure>
327327
<p>这是一个支持回显功能的网络协程服务器(也可以修改成线程模式)。使用协程或线程处理网络通信都可以采用<strong>顺序思维</strong>模式,不必象非阻塞网络编程那样复杂,同时使用协程的最大好处是可以创建大量的协程来处理网络高并发连接,而要创建大量的线程是不现实的(线程数非常多时,会导致操作系统的调度能力下降)。</p>
328+
<p>在上面的示例中,启动协程调度(即调用 <code>acl::fiber::schedule()</code>)时,内部事件引擎为默认的内核级事件引擎,该方法有一个缺省的事件类型参数可以由用户修改,可选的事件引擎如下:</p>
329+
<ul>
330+
<li><strong>acl::FIBER_EVENT_T_KERNEL:</strong> 内核级高效事件引擎,在 Linux 上使用 epoll,FreeBSD&#x2F;MacOS 上使用 kqueue,Windows 平台上则会使用 IOCP;</li>
331+
<li><strong>acl::FIBER_EVENT_T_SELECT, acl::FIBER_EVENT_T_POLL:</strong> 这两个引擎是跨平台的,基本上所有平台都支持;</li>
332+
<li><strong>acl::FIBER_EVENT_T_WMSG:</strong> 当在 Windows 平台开发界面程序时可以使用该引擎,以使网络过程协程化且与界面操作过程同属一个线程空间中,从而可以轻松在网络 IO 过程中操作界面元素;</li>
333+
<li><strong>acl::FIBER_EVENT_T_IO_URING:</strong> 这是在 Linux 5.1x 内核以上新增加的高效事件引擎 io_uring,与 epoll 仅能支持网络(及管道)IO相比,io_uring 引擎同时支持网络 IO 及文件 IO,实现了真正意义上的 IO 大统一,而且 io_uring 引擎为 IO 完成模型,非常容易与协程模式相结合。</li>
334+
</ul>
328335
<h2 id="三、编译安装"><a href="#三、编译安装" class="headerlink" title="三、编译安装"></a>三、编译安装</h2><p>在编译前,需要先从 <strong>github</strong> <a target="_blank" rel="noopener" href="https://github.com/acl-dev/acl">https://github.com/acl-dev/acl</a> 下载源码,国内用户可以选择从 <strong>gitee</strong> <a target="_blank" rel="noopener" href="https://gitee.com/acl-dev/acl">https://gitee.com/acl-dev/acl</a> 下载源码。</p>
329336
<h3 id="3-1、Linux-x2F-Unix-平台上编译安装"><a href="#3-1、Linux-x2F-Unix-平台上编译安装" class="headerlink" title="3.1、Linux&#x2F;Unix 平台上编译安装"></a>3.1、Linux&#x2F;Unix 平台上编译安装</h3><p>在 Linux&#x2F;Unix 平台上的编译非常简单,可以选择使用 make 方式或 cmake 方式进行编译。 </p>
330337
<ul>

local-search.xml

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)