<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>TCP Server 的线程模型 on Dorkytiger 的小屋</title>
    <link>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/</link>
    <description>Recent content in TCP Server 的线程模型 on Dorkytiger 的小屋</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Reactor 模式</title>
      <link>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/01-reactor/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/01-reactor/</guid>
      <description>&lt;p&gt;&lt;strong&gt;单线程 Reactor&lt;/strong&gt;（Redis 就是这种）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;一个 Event Loop（epoll_wait）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  while (true) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    epoll_wait();    // 等待事件
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    for (每个事件) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      if (可读) 读取数据 → 处理请求 → 发送响应
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      if (可写) 继续发送
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      if (新连接) accept
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：没有多线程竞争问题，简单。
&lt;strong&gt;缺点&lt;/strong&gt;：一个请求处理慢了，阻塞所有后续请求。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多线程 Reactor&lt;/strong&gt;（最常见模型）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Main Reactor（一个线程）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  accept 新连接 → 分发给 SubReactor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SubReactor（多个线程，每个一个 epoll）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  epoll_wait(该连接) → 读取数据
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    → 把解析好的请求提交给 ThreadPool 处理
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    → 在工作线程中执行业务逻辑
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    → 工作线程完成后，通知 SubReactor 发送响应
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>Proactor 模式与 io_uring</title>
      <link>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/02-proactor-io-uring/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/02-proactor-io-uring/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Reactor 的问题&lt;/strong&gt;：读取数据的操作是同步的——调用 &lt;code&gt;read()&lt;/code&gt; 后线程阻塞等待数据从内核拷贝到用户缓冲区。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proactor / io_uring&lt;/strong&gt;：你告诉内核&amp;quot;数据读到我指定的缓冲区&amp;quot;，内核完成后通知你。&lt;strong&gt;读数据不阻塞&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Reactor（epoll）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：epoll_wait 告诉我可读了
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：read(fd, buf, len)  ← 这里阻塞等数据拷贝
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：处理数据
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Proactor（io_uring）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：提交 SQE → &amp;#34;把数据读到 buf，完成后通知我&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：干别的事情
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  内核：数据准备好 → DMA 直接拷贝到 buf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  内核：产生 CQE → 通知程序
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：从 CQE 拿到完成的 buf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  程序：处理数据
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;你的 SimpleAsyncLogger 的 Linux 后端 (&lt;code&gt;io_engine_linux.cpp&lt;/code&gt;)&lt;/strong&gt; 用的就是 Proactor 模式——提交 &lt;code&gt;WRITE_FIXED&lt;/code&gt; 后不等待，CQE 完成后处理。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C&#43;&#43; 线程模型怎么选？</title>
      <link>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/03-c/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/03-c/</guid>
      <description>&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模型&lt;/th&gt;
					&lt;th&gt;典型代表&lt;/th&gt;
					&lt;th&gt;适合场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;单线程 Reactor&lt;/td&gt;
					&lt;td&gt;Redis、Node.js&lt;/td&gt;
					&lt;td&gt;I/O 密集、处理快的业务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多线程 Reactor + ThreadPool&lt;/td&gt;
					&lt;td&gt;Nginx、Netty&lt;/td&gt;
					&lt;td&gt;通用网络服务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Proactor (io_uring)&lt;/td&gt;
					&lt;td&gt;SPDK、Seastar&lt;/td&gt;
					&lt;td&gt;极高性能、用户态驱动&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;每个连接一个线程&lt;/td&gt;
					&lt;td&gt;简单 demo&lt;/td&gt;
					&lt;td&gt;连接数少（&amp;lt;1000）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description>
    </item>
    <item>
      <title>结合你已做的</title>
      <link>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/04-section/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/thread-pool-timer/06-tcp-server/04-section/</guid>
      <description>&lt;p&gt;你的 &lt;strong&gt;SimpleAsyncLogger&lt;/strong&gt; 其实已经包含了线程池和定时器的雏形：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AsyncWriter（一个线程）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  while (running) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    1. io_uring_poll() → 处理已完成的 I/O
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    2. 检查是否该日志轮转（定时器行为）
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    3. 检查 TCP 是否该重连（定时器行为）
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    4. 检查是否有新数据 → 提交 io_uring write 和 send
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    5. 超时或满 4KB → flush
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个就是&lt;strong&gt;单线程 Event Loop + 内置定时器&lt;/strong&gt;的模型。面试时你可以说：&amp;ldquo;我的日志库的 AsyncWriter 就是一个简化的 Reactor 模型——单线程事件循环，把定时器检查、I/O 完成处理、任务提交合并到一个循环里。&amp;rdquo;&lt;/p&gt;
&lt;hr&gt;</description>
    </item>
  </channel>
</rss>
