色五月色开心色婷婷色丁香,五月婷婷丁香花综合网,婷婷丁香五月激情综合在线,五月婷婷六月丁香动漫,婷婷丁香五月激情综合在线,丁香花中文字幕在线观看,播五月色五月开心五月网,开心激情综合网,狠狠色丁香婷婷综合最新地址,丁香视频在线观看,狠狠做六月爱婷婷综合av,久久激情五月丁香伊人

ARTICLE DETAIL

資訊詳情

深耕商務建站與企業(yè)官網運營的一線實戰(zhàn)洞察。

Qt工程集成Reactor+epoll+線程池實現(xiàn)高并發(fā)網絡服務

Qt工程集成Reactor+epoll+線程池實現(xiàn)高并發(fā)網絡服務 C 后端開發(fā)進階為什么繞不開“Reactor epoll 線程池”這套組合如果你寫過 Qt 客戶端接觸過網絡通信或多線程編程大概率已經感受到單靠 QThread 和信號槽處理高并發(fā)連接時代碼會變得越來越別扭線程切換開銷高、事件響應不直接、資源管理容易失控。這幾年服務端框架都在提“事件驅動”“非阻塞 I/O”底層核心其實就是這套模型。不過很多人第一次接觸“Reactor”“epoll”“線程池”這幾個詞時都是碎片化地學知道 epoll 比 select 性能好知道線程池能復用線程知道 Reactor 是個事件處理模型但三者在工程上到底怎么協(xié)同卻說不太清楚。尤其是 Qt 開發(fā)者一方面享受著 Qt 事件循環(huán)帶來的便利另一方面又擔心它與高性能 I/O 模型結合時的兼容性和復雜度很容易卡在“看懂了概念卻寫不出能跑通的工程代碼”這一步。這篇文章會從一個具體問題出發(fā)如何用 Qt 的事件循環(huán)框架集成一個基于 epoll 的 Reactor 模型并用線程池處理重邏輯任務。我會用通俗的語言拆解三個核心概念然后給出一個可以直接編譯運行的最小工程演示事件監(jiān)聽、事件分發(fā)、任務異步執(zhí)行三個環(huán)節(jié)如何串起來。最后還會補齊常見問題排查和工程最佳實踐。讀完這篇文章你應該能夠獨立評估自己的項目是否適合這套架構并且有能力在 Qt 工程里動手實現(xiàn)一個簡單的 Reactor 網絡服務雛形。1. 這套技術組合到底解決了什么問題先直說結論Reactor epoll 線程池解決的是高并發(fā)場景下“如何用有限的資源處理海量事件”的問題。它不只是一個面試熱點更是現(xiàn)代 C 網絡服務端的主流設計骨架。沒有這套組合時傳統(tǒng)方案是多線程 阻塞 I/O。來一個連接分配一個線程線程里面阻塞讀取數(shù)據。這種模型有兩個明顯問題。第一線程是昂貴的資源。每個線程都有獨立的棧空間通常默認是 8MB 的虛擬內存線程切換還有上下文切換開銷。當連接數(shù)上升到幾千甚至幾萬時系統(tǒng)資源會迅速耗盡。第二線程大部分時間在空等。一個連接如果沒有數(shù)據到達對應線程就阻塞在 read 或 recv 上CPU 時間片被白白消耗在調度上。連接 10000 個每個連接 1 秒來一次心跳大量線程實際上處于休眠狀態(tài)但系統(tǒng)仍然要為它們付出管理代價。引入 epoll 之后模型發(fā)生了根本變化所有連接的 I/O 事件都由一個線程統(tǒng)一監(jiān)聽真正有數(shù)據到達的 socket 才會被通知。這個“通知”的過程不再遍歷全部 socket而是由內核幫你維護一個就緒列表。這就是 O(1) 級別事件通知能力的來源。引入線程池是為了解決另一個問題Reactor 事件循環(huán)線程不能做耗時操作。如果在一個事件的回調里執(zhí)行數(shù)據庫查詢、文件解析、復雜計算就會阻塞事件循環(huán)導致后續(xù)所有連接的事件響應延遲。線程池把耗時任務從事件循環(huán)里剝離出去讓事件循環(huán)保持“輕、快、不阻塞”。所以這套組合的本質是用 epoll 讓一個線程管住海量連接用 Reactor 把事件分發(fā)做得清晰用線程池把耗時任務隔離出去。三者各管一段彼此配合。很多 Qt 初學者會把 QThread 當作并發(fā)問題的“萬能藥”但實際工程中線程不是越多越好。你應該以“事件驅動 有限線程池”為設計目標而不是“每個連接一個線程”。2. 先用明白 Reactor它是一個事件處理框架不只是一個類Reactor 這個名字聽起來抽象其實它的核心思想非常樸素有一個循環(huán)在持續(xù)等待事件事件到來后調用對應的處理函數(shù)處理完畢回到循環(huán)繼續(xù)等待下一個事件。如果用類比理解它就是餐廳里的“服務鈴”。客人按下鈴服務員過來響應處理完這一桌的需求繼續(xù)等待下一桌按鈴。沒有鈴時服務員不需要挨個去問每桌客人需不需要服務。在代碼層面Reactor 通常包含幾個角色事件源Event Source文件描述符fd比如 socket、管道、事件標志。事件多路分發(fā)器Demultiplexer在 Linux 下最常見的就是 epoll它負責監(jiān)聽多個 fd并告訴你哪些 fd 已經就緒。事件處理器EventHandler針對不同事件調用不同處理邏輯。事件循環(huán)Event Loop不斷調用 epoll_wait拿到就緒事件后分發(fā)給對應處理器。// Reactor 事件循環(huán)的骨架理解這個結構是重點 while (true) { int readyCount epoll_wait(epollFd, events, MAX_EVENTS, timeout); for (int i 0; i readyCount; i) { auto handler handlers[events[i].data.fd]; handler-handleEvent(events[i].events); } }這段骨架代碼是在 Linux 系統(tǒng)編程層面理解 Reactor 的最小入口。它明確告訴你事件循環(huán)線程永遠無法被耗時任務占據否則 epoll_wait 不會在預期時間內返回。在 Qt 環(huán)境中Reactor 的思想有幾個對應物。QEventLoop 本身就是一個事件循環(huán)QSocketNotifier 可以監(jiān)聽 socket 的可讀可寫事件。但 Qt 的事件循環(huán)底層不一定使用 epoll在 Linux 上 Qt 其實會優(yōu)先嘗試使用 glib 的上下文集成而且它對底層事件的封裝對開發(fā)者是屏蔽的。如果你需要在 Qt 工程里精確控制 I/O 多路復用通常會自己管理一個線程在該線程中創(chuàng)建 epoll 實例而不是把 epoll 直接塞進主線程的 QEventLoop 里。這個判斷很重要Qt 可以承載 Reactor 的工程結構但 epoll 的線程最好獨立管理并通過 Qt 的信號槽或自建的線程安全隊列把結果傳回主線程。這是集成時最容易做錯的地方。3. epoll 為什么快以及和 select/poll 的直觀對比epoll 是 Linux 內核提供的 I/O 事件通知機制核心能力是讓一個線程同時監(jiān)聽大量文件描述符并且只關注真正就緒的那些。要理解 epoll 的優(yōu)勢最好的方式是和 select、poll 做對比。select 的工作方式是把所有 fd 集合從用戶態(tài)拷貝到內核態(tài)內核逐個檢查 fd 狀態(tài)再把結果拷回用戶態(tài)。fd 越多線性掃描的成本越高而且 fd 數(shù)量還受 FD_SETSIZE 限制通常是 1024。poll 采用了鏈表結構突破了 fd 數(shù)量限制但它仍然需要把所有 fd 傳給內核并且返回后你必須遍歷整個數(shù)組才能知道哪些 fd 就緒。連接一萬個每次執(zhí)行 poll 都是 O(N) 的掃描。epoll 不同。它維護了一個由內核管理的興趣列表你只需要通過 epoll_ctl 告訴內核“我關心哪個 fd 的哪些事件”之后等待時內核負責把就緒事件放到一個就緒鏈表里epoll_wait 返回時你只需要處理就緒鏈表里的 fd 即可。性能與活躍連接數(shù)有關與總連接數(shù)無關。用一個表來直觀對比對比項selectpollepollfd 數(shù)量限制有限1024 左右基本無限制基本無限制事件獲取方式遍歷全部 fd遍歷全部 fd直接拿到就緒鏈表時間復雜度O(N)O(N)O(就緒事件數(shù))內核態(tài)用戶態(tài)拷貝每次拷貝全部 fd每次拷貝全部 fd通過 mmap 等方式減少拷貝跨平臺支持廣支持較廣Linux 專屬epoll 還提供了兩種觸發(fā)模式這在實際工程中很容易踩坑。水平觸發(fā)Level-TriggeredLT只要 fd 上有未處理的數(shù)據epoll_wait 每次都會返回該 fd。優(yōu)點是編程簡單不要求一次性把數(shù)據讀完。缺點是如果你處理太慢會被同一個 fd 反復喚醒。邊緣觸發(fā)Edge-TriggeredET只有當 fd 的狀態(tài)發(fā)生變化比如從無數(shù)據變?yōu)橛袛?shù)據時epoll_wait 才會返回該 fd。你必須一次性把數(shù)據讀完否則會丟失后續(xù)數(shù)據到達的通知。ET 模式配合非阻塞 I/O 是高性能服務器的常見配置但它對代碼的嚴謹性要求更高。在 Qt 工程里如果你只是想在項目中引入 epoll 做實驗建議先從 LT 模式開始跑通完整流程后再嘗試 ET。LT 模式產生的 bug 更少更適合初學者建立正確的心智模型。4. 線程池不是“有線程就并發(fā)”那么簡單的資源治理線程池的核心價值在于復用線程和削峰填谷。反復創(chuàng)建和銷毀線程是有代價的線程池提前創(chuàng)建一批工作線程把任務放入隊列由線程循環(huán)取出并執(zhí)行。這樣既減少了線程創(chuàng)建開銷也限制了并發(fā)線程數(shù)量避免系統(tǒng)資源被極端峰值打穿。線程池通常由三個部分組成任務隊列存放待執(zhí)行的任務。工作線程組一組處于等待狀態(tài)的線程。調度器負責任務入隊、線程喚醒和資源回收。在 C 標準庫中從 C11 開始提供了 std::thread從 C17 開始加入了 std::scoped_lock而 C20 則提供了 std::jthread。但標準庫一直沒有直接提供線程池實現(xiàn)。所以工程實踐中要么自己封裝線程池要么依賴 Qt 的 QThreadPool要么引入第三方庫。Qt 的 QThreadPool 是一個成熟的線程池實現(xiàn)配合 QRunnable 使用非常方便。但在高頻、低延遲的網絡服務場景中QThreadPool 的調度粒度和信號槽傳遞方式可能不夠直接。很多 C 服務端工程師更傾向于自己維護一個基于 std::thread 和 std::queue std::condition_variable 的線程池因為這樣可控性最高。一個最小線程池通常長這樣// 文件路徑ThreadPool.h #pragma once #include atomic #include condition_variable #include functional #include mutex #include queue #include thread #include vector class ThreadPool { public: explicit ThreadPool(size_t threadCount) : stop_(false) { for (size_t i 0; i threadCount; i) { workers_.emplace_back([this] { while (true) { std::functionvoid() task; { std::unique_lockstd::mutex lock(queueMutex_); condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); }); if (stop_ tasks_.empty()) { return; } task std::move(tasks_.front()); tasks_.pop(); } task(); } }); } } ~ThreadPool() { { std::unique_lockstd::mutex lock(queueMutex_); stop_ true; } condition_.notify_all(); for (auto worker : workers_) { worker.join(); } } template typename Func void enqueue(Func func) { { std::unique_lockstd::mutex lock(queueMutex_); if (stop_) { return; } tasks_.emplace(std::forwardFunc(func)); } condition_.notify_one(); } private: std::vectorstd::thread workers_; std::queuestd::functionvoid() tasks_; std::mutex queueMutex_; std::condition_variable condition_; std::atomicbool stop_; };這個線程池實現(xiàn)雖然精簡但已經包含了任務隊列、互斥鎖、條件變量和線程回收機制。在實際項目中通常還需要支持返回任務結果、任務優(yōu)先級、動態(tài)調整線程數(shù)等能力。線程池面臨的真正挑戰(zhàn)是任務隊列的阻塞策略。如果任務隊列是無界的當任務產生速度遠超消費速度時內存會被任務對象占滿。如果隊列是有界的任務入隊時隊列已滿該怎么辦這個問題在面試中經常出現(xiàn)也就是“線程池的阻塞隊列選擇”。工程上常見的方案有拋出異常、丟棄任務、阻塞調用方、由調用線程直接執(zhí)行等方式。更穩(wěn)妥的設計是為任務隊列設置容量上限配合拒絕策略告警。回到 Qt 場景當你用一個 Reactor 線程監(jiān)聽事件然后想把某個耗時任務丟給線程池時最安全的做法是在任務函數(shù)內部捕獲所有異常并通過信號或回調把結果傳回主線程而不是直接操作 Qt Widget 或 QMainWindow。Qt 的 UI 操作必須在主線程執(zhí)行這是跨線程開發(fā)的紅線。5. 環(huán)境準備與前置條件為了跑通下面的示例你需要準備以下環(huán)境操作系統(tǒng)Linux因為 epoll 是 Linux 系統(tǒng)調用Windows 不支持編譯器GCC 或 Clang要求支持 C17 標準Qt 版本Qt 5.12 或更高示例核心不依賴 Qt 特有機制但工程結構使用 Qt 的項目組織方式CMake3.10 或更高如果你的機器還沒有安裝 Qt可以到 Qt 官網獲取對應版本的安裝包。安裝完成后在 CMake 里通過 find_package 找到 Qt 組件。下面是一個 CMakeLists.txt 的最小配置示例# 文件路徑CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(QtReactorDemo VERSION 1.0) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt5 COMPONENTS Core Network Widgets REQUIRED) add_executable(QtReactorDemo main.cpp ReactorServer.h ReactorServer.cpp ThreadPool.h ) target_link_libraries(QtReactorDemo Qt5::Core Qt5::Network Qt5::Widgets )Linux 下編譯這個工程之前請確認內核版本支持 epoll2.6 之前的內核不支持現(xiàn)在絕大多數(shù)發(fā)行版都沒問題。如果使用虛擬機要注意網絡設備模式對 socket 行為的影響最好先使用回環(huán)地址 127.0.0.1 測試。6. 核心流程拆解如何把 epoll 和線程池裝進 Qt 工程從架構層面看集成方案分成四步。第一步規(guī)劃線程邊界。我們至少要設計兩個線程域主線程運行 QApplication/QCoreApplication負責 UI 或業(yè)務邏輯接收線程池回傳的結果。Reactor 線程獨立創(chuàng)建運行 epoll 事件循環(huán)不直接做耗時任務。如果業(yè)務負載很重可以在 Reactor 線程中再拆分一部分線程處理 accept、read、write另一部分線程池處理計算任務。但最小示例只需要一個 Reactor 線程加一個線程池。第二步創(chuàng)建 Reactor 線程。在 Qt 中最簡單的方式不是繼承 QThread而是使用 std::thread 啟動一個函數(shù)讓函數(shù)內部運行 epoll 循環(huán)。QThread 在這里并不是必需的因為 epoll 循環(huán)完全不用 Qt 事件循環(huán)。用 std::thread 可以減少和 Qt 線程模型的耦合。第三步管理 socket 生命周期。所有被 epoll 監(jiān)聽的 fd 需要維護在 Reactor 線程內部的數(shù)據結構中。注意不要在多個線程中同時操作同一個 fd 的 epoll_ctl 調用否則可能出現(xiàn)難以排查的競態(tài)問題。第四步與主線程通信。當 Reactor 線程處理完網絡 I/O需要通知主線程時可以使用 Qt 的信號槽也可以使用自定義的線程安全隊列。需要注意的是從非 Qt 線程發(fā)送信號時必須使用 Qt::QueuedConnection或者通過 QMetaObject::invokeMethod 來安全地調用主線程對象的方法。下面用簡單的文字流程描述一次完整的事件處理客戶端連接到達監(jiān)聽 fd 變成可讀。epoll_wait 返回該事件。Reactor 線程調用 accept 接收新連接并把新連接的 fd 加入 epoll 監(jiān)聽列表??蛻舳税l(fā)送業(yè)務數(shù)據。新連接 fd 變?yōu)榭勺xepoll_wait 再次返回。Reactor 線程讀取數(shù)據解析出業(yè)務請求。Reactor 線程把數(shù)據包封裝成一個任務提交給線程池。線程池空閑線程取出任務執(zhí)行得到響應內容。Reactor 線程通過線程安全隊列或信號拿到響應把它寫回客戶端 fd。整個鏈路中第 6 步到第 8 步之間Reactor 線程沒有執(zhí)行任何耗時操作這是系統(tǒng)保持高性能的關鍵。7. 完整示例ReactorServer 實現(xiàn)下面給出一個可以在 Linux 上編譯運行的完整示例。它會在本機 8080 端口建立 TCP 服務用 epoll 監(jiān)聽事件收到客戶端請求后把處理邏輯丟給線程池完成后返回一條帶線程 ID 的響應。為了在 Qt 工程中演示跨線程回傳這里選擇簡潔的回調 原子計數(shù)方式避免引入過多 Qt 信號槽代碼。實際項目中你可以將回調替換為跨線程信號但思想完全一致。7.1 ThreadPool 頭文件// 文件路徑ThreadPool.h #pragma once #include atomic #include condition_variable #include functional #include mutex #include queue #include thread #include vector class ThreadPool { public: explicit ThreadPool(size_t threadCount) : stop_(false) { for (size_t i 0; i threadCount; i) { workers_.emplace_back([this] { while (true) { std::functionvoid() task; { std::unique_lockstd::mutex lock(queueMutex_); condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); }); if (stop_ tasks_.empty()) { return; } task std::move(tasks_.front()); tasks_.pop(); } task(); } }); } } ~ThreadPool() { { std::unique_lockstd::mutex lock(queueMutex_); stop_ true; } condition_.notify_all(); for (auto worker : workers_) { worker.join(); } } template typename Func void enqueue(Func func) { { std::unique_lockstd::mutex lock(queueMutex_); if (stop_) { return; } tasks_.emplace(std::forwardFunc(func)); } condition_.notify_one(); } private: std::vectorstd::thread workers_; std::queuestd::functionvoid() tasks_; std::mutex queueMutex_; std::condition_variable condition_; std::atomicbool stop_; };7.2 ReactorServer 頭文件// 文件路徑ReactorServer.h #pragma once #include atomic #include functional #include mutex #include thread #include unordered_map #include ThreadPool.h class ReactorServer { public: using OnClientMessage std::functionvoid(const std::string ); ReactorServer(int port, size_t threadCount 4); ~ReactorServer(); void start(); void stop(); void setMessageHandler(OnClientMessage handler); private: void eventLoop(); void handleAccept(int listenFd, int epollFd); void handleRead(int clientFd, int epollFd); int listenFd_ -1; int epollFd_ -1; int port_ 0; std::atomicbool running_{false}; std::thread reactorThread_; ThreadPool pool_; OnClientMessage handler_; };7.3 ReactorServer 實現(xiàn)文件// 文件路徑ReactorServer.cpp #include ReactorServer.h #include arpa/inet.h #include errno.h #include fcntl.h #include netinet/in.h #include string.h #include sys/epoll.h #include sys/socket.h #include unistd.h #include iostream ReactorServer::ReactorServer(int port, size_t threadCount) : port_(port), pool_(threadCount) {} ReactorServer::~ReactorServer() { stop(); } void ReactorServer::setMessageHandler(OnClientMessage handler) { handler_ std::move(handler); } void ReactorServer::start() { if (running_) { return; } // 1. 創(chuàng)建監(jiān)聽 socket listenFd_ ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if (listenFd_ 0) { std::cerr socket create failed: strerror(errno) std::endl; return; } int opt 1; setsockopt(listenFd_, SOL_SOCKET, SO_REUSEADDR, opt, sizeof(opt)); sockaddr_in addr; memset(addr, 0, sizeof(addr)); addr.sin_family AF_INET; addr.sin_addr.s_addr htonl(INADDR_ANY); addr.sin_port htons(port_); if (::bind(listenFd_, reinterpret_castsockaddr *(addr), sizeof(addr)) 0) { std::cerr bind failed: strerror(errno) std::endl; ::close(listenFd_); listenFd_ -1; return; } if (::listen(listenFd_, 128) 0) { std::cerr listen failed: strerror(errno) std::endl; ::close(listenFd_); listenFd_ -1; return; } // 2. 創(chuàng)建 epoll 實例 epollFd_ ::epoll_create1(0); if (epollFd_ 0) { std::cerr epoll_create1 failed: strerror(errno) std::endl; ::close(listenFd_); listenFd_ -1; return; } epoll_event ev; memset(ev, 0, sizeof(ev)); ev.events EPOLLIN; ev.data.fd listenFd_; if (::epoll_ctl(epollFd_, EPOLL_CTL_ADD, listenFd_, ev) 0) { std::cerr epoll_ctl add listen fd failed std::endl; ::close(epollFd_); ::close(listenFd_); listenFd_ -1; return; } running_ true; reactorThread_ std::thread([this] { eventLoop(); }); std::cout Reactor server started on port port_ std::endl; } void ReactorServer::stop() { if (!running_) { return; } running_ false; // 通過關閉監(jiān)聽 fd 和 epoll fd 觸發(fā) eventLoop 返回 if (listenFd_ 0) { ::close(listenFd_); listenFd_ -1; } if (epollFd_ 0) { ::close(epollFd_); epollFd_ -1; } if (reactorThread_.joinable()) { reactorThread_.join(); } } void ReactorServer::eventLoop() { constexpr int MAX_EVENTS 64; epoll_event events[MAX_EVENTS]; while (running_) { // 超時設為 100ms可以定期檢查 running_ 狀態(tài) int n ::epoll_wait(epollFd_, events, MAX_EVENTS, 100); if (n 0) { if (errno EINTR) { continue; } std::cerr epoll_wait error: strerror(errno) std::endl; break; } for (int i 0; i n; i) { int fd events[i].data.fd; uint32_t eventMask events[i].events; if (fd listenFd_) { handleAccept(fd, epollFd_); } else { if (eventMask (EPOLLERR | EPOLLHUP)) { ::close(fd); continue; } if (eventMask EPOLLIN) { handleRead(fd, epollFd_); } } } } std::cout Reactor event loop exited std::endl; } void ReactorServer::handleAccept(int listenFd, int epollFd) { while (true) { sockaddr_in clientAddr; socklen_t clientLen sizeof(clientAddr); int clientFd ::accept4(listenFd, reinterpret_castsockaddr *(clientAddr), clientLen, SOCK_NONBLOCK); if (clientFd 0) { if (errno EAGAIN || errno EWOULDBLOCK) { break; } if (errno EINTR) { continue; } std::cerr accept error: strerror(errno) std::endl; break; } char ip[INET_ADDRSTRLEN] {0}; inet_ntop(AF_INET, clientAddr.sin_addr, ip, sizeof(ip)); std::cout New connection from ip : ntohs(clientAddr.sin_port) std::endl; epoll_event ev; memset(ev, 0, sizeof(ev)); ev.events EPOLLIN | EPOLLET; // 邊緣觸發(fā) ev.data.fd clientFd; if (::epoll_ctl(epollFd, EPOLL_CTL_ADD, clientFd, ev) 0) { std::cerr epoll_ctl add client fd failed std::endl; ::close(clientFd); } } } void ReactorServer::handleRead(int clientFd, int epollFd) { char buffer[4096]; std::string request; // ET 模式需要循環(huán)讀取直到 EAGAIN while (true) { ssize_t n ::read(clientFd, buffer, sizeof(buffer)); if (n 0) { request.append(buffer, n); } else if (n 0) { // 對方關閉 ::epoll_ctl(epollFd, EPOLL_CTL_DEL, clientFd, nullptr); ::close(clientFd); std::cout Client closed: clientFd std::endl; return; } else { if (errno EAGAIN || errno EWOULDBLOCK) { break; } if (errno EINTR) { continue; } ::epoll_ctl(epollFd, EPOLL_CTL_DEL, clientFd, nullptr); ::close(clientFd); return; } } if (request.empty()) { return; } std::cout Received request.size() bytes from fd clientFd std::endl; // 把響應計算丟給線程池避免阻塞事件循環(huán) int targetFd clientFd; std::string payload request; pool_.enqueue([this, targetFd, payload]() { // 獲取線程 ID方便演示 auto tid std::this_thread::get_id(); std::string response echo[ payload ] handled by thread std::to_string(reinterpret_castunsigned long long(tid) % 1000); // 響應寫回。此處簡單用 ::send生產環(huán)境需考慮寫緩沖和非阻塞寫法 ::send(targetFd, response.data(), response.size(), 0); }); }7.4 main.cpp// 文件路徑main.cpp #include ReactorServer.h #include QCoreApplication #include QTimer #include csignal #include iostream static std::atomicbool g_stopFlag{false}; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); int port 8080; if (argc 1) { port std::atoi(argv[1]); } ReactorServer server(port, 4); server.setMessageHandler([](const std::string msg) { std::cout [handler] msg std::endl; }); server.start(); // 用 QTimer 周期性檢查運行狀態(tài)方便安全退出 QTimer timer; QObject::connect(timer, QTimer::timeout, []() { if (g_stopFlag) { server.stop(); app.quit(); } }); timer.start(500); std::cout Qt Reactor demo running. Press CtrlC to stop. std::endl; return app.exec(); }代碼中有幾個要點需要解釋。第一為什么使用 accept4可以直接在接受連接時設置為非阻塞避免額外調用 fcntl減少一次系統(tǒng)調用。第二ET 模式下循環(huán)讀取的意義。邊緣觸發(fā)只通知一次如果不在一次通知里把所有數(shù)據讀完剩余數(shù)據不會再觸發(fā)可讀事件。因此代碼在 handleRead 里用了 while 循環(huán)一直讀到 EAGAIN 為止。這里即使業(yè)務上是短請求也建議養(yǎng)成循環(huán)讀取的習慣。第三線程池里直接調用 ::send 寫回響應。嚴格說這不是最佳做法因為 send 在緩沖區(qū)滿時可能阻塞線程池線程。但作為最小演示它會讓你更直觀地看到“I/O 事件循環(huán)不阻塞、任務在池中執(zhí)行”的效果。生產環(huán)境中更穩(wěn)妥的做法是把響應發(fā)送也放入一套非阻塞發(fā)送隊列。第四stop 的優(yōu)雅退出策略。這里通過關閉 epollFd 讓 epoll_wait 返回錯誤從而退出循環(huán)。更優(yōu)雅的方案是創(chuàng)建一個 eventfd 或管道在 stop 時寫入數(shù)據喚醒事件循環(huán)。如果你的工程需要長時間運行建議把事件循環(huán)的喚醒改成 eventfd 方式。7.5 編譯與運行在 Linux 終端中執(zhí)行以下命令mkdir build cd build cmake .. make -j$(nproc) ./QtReactorDemo如果編譯過程中遇到找不到 Qt5 組件的問題請檢查 CMAKE_PREFIX_PATH 是否指向 Qt 安裝目錄。例如cmake .. -DCMAKE_PREFIX_PATH/opt/Qt/5.15.2/gcc_64運行后你可以打開另一個終端用 nc 命令測試echo hello reactor | nc 127.0.0.1 8080預期輸出中會包含以下關鍵信息Reactor server started on port 8080 New connection from 127.0.0.1:xxxxx Received 13 bytes from fd8 echo[hello reactor ] handled by thread 123注意nc 發(fā)送的字符串可能包含換行符所以 echo 后的內容會多出一個換行這是正常的。關鍵在于接收、線程池處理、響應寫回三個環(huán)節(jié)都能正常工作。如果運行時報錯第一步可以這樣排查查看端口是否被占用使用netstat -tlnp | grep 8080或ss -tlnp。如果被占用換一個端口。確認防火墻沒有屏蔽本機回環(huán)默認 127.0.0.1 不會受防火墻影響但如果你用遠程 IP 測試請確認安全組規(guī)則。觀察控制臺是否打印了Reactor server started。如果沒有檢查 bind 和 listen 的錯誤信息。8. 常見問題與排查思路在實際集成過程中下面幾個問題出現(xiàn)的頻率非常高這里整理成排查表。問題現(xiàn)象可能原因排查方式解決方案epoll_wait 被信號打斷返回 -1EINTR查看 errno是否等于 EINTR在循環(huán)中捕獲 EINTR 并 continue客戶端連接建立后服務端收不到數(shù)據連接 fd 被阻塞或 ET 模式沒有循環(huán)讀檢查 accept4 是否設置了 SOCK_NONBLOCK檢查 handleRead 是否為循環(huán)讀取統(tǒng)一使用非阻塞 fd讀到 EAGAIN 才退出QCoreApplication 一退出Reactro 線程崩潰析構順序問題Reactro 線程還在使用已銷毀的 epoll fd 或 Qt 對象gdb 查看崩潰堆棧在 app.quit 前先 stop server提供 stop 接口先停 Reactor 線程再退出 Qt 事件循環(huán)線程池任務執(zhí)行耗時過長全部線程卡住線程池線程數(shù)太少或任務自身發(fā)生死鎖打印線程池任務隊列長度和線程狀態(tài)為線程池增加任務隊列長度告警重新評估線程數(shù)和任務拆分方式響應順序和請求順序不一致多線程并發(fā)執(zhí)行任務日志記錄請求序號和響應序號如果業(yè)務強依賴順序對同一連接做串行化處理send 返回 EAGAIN 導致數(shù)據丟失寫緩沖區(qū)滿非阻塞 socket 需要排隊發(fā)送不做處理會丟包引入寫緩沖隊列在 EPOLLOUT 事件中繼續(xù)發(fā)送程序中同時處理 Qt 信號和 epoll 事件時偶發(fā)崩潰跨線程訪問同一個 socket fd 或 Qt 對象檢查日志中是否在非 Qt 線程操作 UI定義清晰的線程模型禁止跨線程直接訪問未經同步的對象這些問題的共同根源往往是“線程模型沒有理清”。寫這種網絡服務代碼時不要把 epoll fd、連接 fd、線程池狀態(tài)看得太簡單。每發(fā)生一次崩潰先問自己這個變量被哪些線程訪問了是否有鎖保護生命周期是否清晰9. 在 Qt 工程中落地的工程建議這部分是對真實生產環(huán)境的經驗總結不是概念堆砌。9.1 線程模型先于代碼設計在動手寫代碼之前先畫出線程邊界圖。你的工程里至少要有這些角色主線程Qt 事件循環(huán)管理 UI 和業(yè)務入口I/O 線程運行 epoll 事件循環(huán)建議只做事件分發(fā)和少量輕邏輯工作線程池執(zhí)行耗時任務如果業(yè)務量繼續(xù)擴大可以把 I/O 線程擴展成多個按連接哈希分配到不同 I/O 線程。但首要原則是一個 fd 同一時間只能在一個線程中處理通過 epoll 監(jiān)聽關系決定歸屬。遷移 fd 時要小心競態(tài)。9.2 信號槽跨線程必須謹慎Qt 的信號槽默認在發(fā)送者線程執(zhí)行除非連接方式為 Qt::QueuedConnection。當你在非 Qt 線程需要通知主線程時推薦使用 QMetaObject::invokeMethod 指定 QueuedConnection或者直接調用 signal 時設置連接類型。千萬不要假設“只在 Qt 對象里加鎖就安全”Qt 對象的事件循環(huán)與鎖機制是兩回事。9.3 網絡數(shù)據包處理需要分幀上面示例中直接按 read 到的字節(jié)作為請求。真實項目中TCP 是字節(jié)流沒有天然消息邊界。你需要自定義協(xié)議頭比如“4 字節(jié)長度 消息體”并在讀取時進行粘包和半包處理。這是網絡編程最基本也最重要的基本功。9.4 使用 eventfd 喚醒事件循環(huán)如果你需要優(yōu)雅退出強烈建議注冊一個 eventfd 到 epoll 監(jiān)聽列表。stop 時向 eventfd 寫入數(shù)據事件循環(huán)會正常退出而不是依賴關閉 epollFd 這種“準暴力”方式。這樣能保證正在處理的事件被正確回收。9.5 線程池的異常吞掉問題線程池執(zhí)行函數(shù)一旦拋出未捕獲異常std::thread 會默認調用 std::terminate整個程序會崩潰。在線程池的任務四周包一層 try-catch 是必要防御?;蛘咧辽賹惓2东@后傳入日志系統(tǒng)。pool_.enqueue([this, targetFd, payload]() { try { // 業(yè)務邏輯 } catch (const std::exception e) { std::cerr task error: e.what() std::endl; } catch (...) { std::cerr task unknown error std::endl; } });9.6 性能監(jiān)控與壓測不要以為實現(xiàn)了模型就萬事大吉。發(fā)布前必須用工具驗證。最簡單的方式是使用abApacheBench或wrk做 HTTP 壓測對于原生 TCP 協(xié)議可以寫一個壓測客戶端模擬多個并發(fā)連接。重點觀察QPS 或每秒請求數(shù)。事件循環(huán)線程的 CPU 占用率。如果它接近 100%說明事件分發(fā)層有瓶頸。線程池任務隊列積壓量。如果持續(xù)增長說明線程池容量不足。響應延遲的 P99。不要只看平均延遲。9.7 如何用 Qt 組件輔助調試Qt 的 QLoggingCategory 非常適合做分類日志。你在 ReactorServer 中可以按模塊區(qū)分日志方便線上排查Q_LOGGING_CATEGORY(lcReactor, app.reactor) Q_LOGGING_CATEGORY(lcPool, app.pool)這樣在 main.cpp 中通過設置環(huán)境變量即可打開指定模塊日志QT_LOGGING_RULESapp.reactor.debugtrue;app.pool.debugtrue ./QtReactorDemo這個技巧在大型 Qt 工程中非常實用它讓你不需要改代碼就能靈活控制日志粒度。10. 何時你并不需要這套架構最后說點實際的。Reactor epoll 線程池不是萬能的也不是所有項目都需要它。如果你的 Qt 程序只是一個客戶端工具偶爾連接幾個服務器那么直接用 QTcpSocket 和 QThreadPool 就足夠了。QSocketNotifier 已經幫你處理了底層事件再用原生 epoll 屬于重復造輪子。如果你的項目是服務端但并發(fā)連接數(shù)長期只有幾百epoll 帶來的提升也不如代碼可維護性重要。使用 Qt 的 QTcpServer 線程池開發(fā)效率更高跨平臺性更好。需要引入這套架構的典型場景是長連接數(shù)量大比如物聯(lián)網設備接入網關。每個連接空閑時間遠大于活躍時間心跳?;蠲芗?。需要在單機上支撐上萬個 socket 連接。業(yè)務方明確要求自研網絡層以便精確控制收發(fā)緩沖區(qū)和背壓。從個人技術成長角度理解這套模型的價值不取決于你是否立刻用它。它幫助你看懂很多開源項目比如 Muduo、Boost.Asio、Netty 的設計思路。當你看代碼時不再只看到一堆類而是能看到“事件循環(huán)在哪里、哪個線程在跑、任務如何被轉移”你的 C 后端水平就會真正上一個臺階。下一步建議你親自做一個練習把這個最小示例改成不使用 Qt 組件的純 C 版本并加入 HTTP 解析能力。之后再嘗試把監(jiān)聽 accept、讀事件、寫事件分別拆成三個 handler模擬 Muduo 的 架構風格。這個過程比看十篇文章都有用。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲精品 欧美97色色| 上海一级黄片| 激情久久久| 欧美亚洲日韩16色| 无码人妻一区二区三区色欲aⅴ| 天天操夜夜嗨| 久久超碰97中文字幕| 国产精品一区二区麻豆| 亚洲欧美自拍偷拍| 色呦呦、国产精品| 国产视频97| 极品销魂美女一区二区| 国产精品熟女九色九色蜜臀| 国产suv精品一区二区四| 91色堂| 欧美少妇色图| 久久精品人体| 亚洲资源一区| 日韩一级欧美一级在线观看| 好爽要喷了| 精品国产一区二区三区四区在线看 | 日韩人成网站在线播放| 九热超碰| 操逼网免费无码视频| 欧洲亚洲人妻无码中字久久三区四区 | 欧美91精彩| 综合久久少妇中文字幕| 亚洲色图a| 日韩三A大片在线观看| 日韩精品三区四区| 亚洲国产成人精品久久久国产成人一区二区 | 久久毛卡| 超碰欧美97资源| 大香蕉免费3| 台欧久久精品视频| 午夜性生活av免费在线看| 大香樵伊人网| 日韩偷拍一区二区三区| 九七毛片九九毛片| 无码色| 国产综合久久久麻桃个| 一区二区三区国产精产| 最近2019中文字幕国语免费版| 96精品久久久| 亚洲日本男人天堂网| 人人潮人人摸| 超碰人妻久久| 97频视在线| 13小男生GAY自慰脱裤子| 2021国产成人精品久久| 99久久久久久亚洲精品不卡| 久久精品—区二区三区内射| 青青草色插素人| 熟女自慰久久久| 麻豆福利视频导航| 人妻人人澡人人爽人人| 丝袜夫妻自拍| 超碰久久性爱| 久久色激情一区二区三区| 色婷婷五月天| 人妻久久久久久久久久久久久久久 | 蜜臀AV成人精品蜜臀AV久久| 综合国产97| 六六久久日韩不卡| 这里只有精品视频在线| 婷婷五月天在线观看| 国产毛片精品一区二区色欲黄A片| 亚洲成人性爱在线观看| 亚洲高清在线| av天堂影视中文在字幕在线中文| 婷婷精品| 日日夜夜草草草| 一区二区三区成人| 丰满少妇精品一区二区| 精品九九| 一区二区三区黄片免费观看| 久操网无码在线| 一本精品日本在线视频精品| 日韩视频啪啪| 天美av在线观看| 欧美中文字幕一区 | 丁香婷婷激情五月天无毒不卡| 97se综合网| 综合网~91综合网| 五月天日日操夜夜操| 人妻激情视频| 啪啪性爱免费视频| 欧美有码激情视频一区二区三区| 亚洲少妇激情视频| 欧洲综合色| 少妇久久久久久久久| 大香蕉久| 亚洲情色1区| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 久久偷拍人| 成人精品在线观看| 日韩操逼性鲍| 艹比视频国产精品| 大香蕉97久久| 人妻内射一区二区在线视频| 91亚洲欧洲| 人妻 丝袜美腿 中文字幕| 操逼操逼逼操操逼91 | 久久99操天天日| 欧美后入式| 男人的天堂网页| 久久性爱城| 麻豆一区二区三区精品| 国产捆绑一区| 九九热免费国产视频婷婷伊人 | 高清无码国产亚洲| 啊啊啊好舒服视频在线观看| 91综合网在线| 欧美日韩国产在线| 女优大全 - 91n| 安徽熟妇视频| 日本精品国产视频| 人看人人摸人人操| 女沟厕偷窥piss小便| 久久超碰、| 在线无码操| 婷婷激情四射| 色偷综合| 精品久久99| 中文字幕一区二区韩| 天美麻豆一区二区三区| 欧美日韩亚洲五月天婷婷| 日韩精品黄片免费观看| 欧美成熟性爱精品| 欧美色图电影| 中文字幕欧美精品亚洲日韩蜜臀| 亚洲一二三精品久久网| 日本福利二区视频| 婷婷中文网| 亚洲一区二区三区在线激情| 99久在线精品99re8蜜桃| av在线人气| 手机看片1025| av在线免费一区二区| 日韩97P| 91熟女少妇| 国产传媒美日韩av| 黄总AV色图| 久久,精品一二三| 亚洲黄网在哪免费看| 色欲Av人妻精品一区二| 88xx成人精品视频| 久久亚洲中文字幕视频| 日本人妻丰满熟妇久久久久久 | 亚洲国产成人高清在线| 破苞ⅩXXX性无码动漫无码| 精品高清av中文字幕| 99re免费| 乱伦熟妇一区二区| 中文字幕一区二区三区字幕| 中字幕人妻一区二区三区| 欧美精品三区| 天天看天天干| 人人 操人人 操人人| 国内精品久久人妻性色av| 伊人影院日本| 国产精品ⅴ无码大片在线看.| 色色毛片| 99久久久久久久久| 五月天社区| 日韩精品国产精品五码一区二区| 久久天天摸| 香蕉一区二区三区在线视频| 伦理弟一页| 热热色国产一二区AV| 亚洲,欧美,综合网| 麻豆国产97在线| 中文字幕第9页萱萱影音先锋 | 啊啊啊啊二区好大| AV在线播放网址| 精品人妻av区天天看片| 岛国1区2区3区在线观看| 国产探花精品在线| 天天干天天干天天干| 亚洲综合图文| 人妻第一页| 99re免费视频精品全部| 五月婷婷激情综合| 伊人精品视频| 日韩精品人妻| 黑人黄片在线免费观看| 亚洲视频一二区| 国产精品69久久久久久久| 私人尤物在线精品不卡| 美女爽爽爽刺痛洞洞| 在线 制服丝袜中出 人妻| 色图综合网| 老熟女综合网| 99热色精品| 黄片免费视频2019| 动漫av中文| 蜜臀久久99精品| 日韩黄色成人性爱| 国产精品成人AV片免费看网站| 亚州春色| 欧美亚洲综合色| 国产一级不卡在线观看| 亚洲色阁| 极品少妇久久久久| 色一射色一射| 欧美草草高清日韩视频| 青青草伊人久久| 夜夜一区二区| 99精品久久久久久久婷婷蜜桃| 国产午夜精品在线观看| 国产精品久久发布| 日本国产欧美一区三区二区| 日本人人操人人操| 国产亚洲精品久久久久小| 青娱乐黄色录像| 人妻人久久精品中文字幕| 一类av片在线看| 欧美极品少妇| 色妹子A V| 国产精品日本无码A片| 大乔未久88一区| 97操碰| 97国产高清视频在线观看| 久久超碰国产一区二区三区| 2024年最新色情网站在线观看| 熟妇女伦乱视频| 久久色精品视频在线| 91美女视频在线观看| 国产精品熟女一区二区三区| 在线午夜成人无码视频| 嫩草影院在线观看精品| 中文字幕性感少妇av| 777奇米影视777四色| 亚洲色欲天天人妻无码系列专区| 丁香六月啪啪| 婷婷色香| 懂色影视久久| 夜色91| 边做饭边操逼逼| 国产日韩欧美亚洲精品95 | 粉嫩av一区二区三区四季| 黄久在线| 99re这里只有精品9| 国产精品不卡一区二区三区av| 欧美性生活男人的天堂| 天天看,天天做| 骚逼高潮久久精品| 青青欧洲黑| 天美av在线| 久久大黄片| 在线国产福利网址导航| 最新欧洲欧美日本激情网站| 久久伦理视频久久大香蕉视频| 懂色av中文字幕| 神马麻豆福利院| 日本操逼aaaaa| 蜜乳AV一区二区三区四| 日本一区二区电影网站| 欧美综合狠| 中文字幕丰满子伦无码专区在线视频最新| 日韩在线一区二区| 国产精品电影| 久久久国产精品亚洲精品| 97欧美日韩精品| 国产91会所女技师在线观看| 无码国产精品午夜不卡(| 在现视频女上位好爽| 强奸熟女一区二区三区 | 日韩无码黄色片| 天天插天天射| 日本一久是| 老司机午夜精品视频| 欧美人妻久久精品二区三区| 人妻一区二区三区| 97超碰超| 91动漫操逼视频| 天堂资源欧美| 操熟女91| 久久久久国产无av| 一区二区不卡免费| 尤物视频一区| 99热在线不卡| 超碰日韩人妻| 久久久久日本视| 玖玖爱综合网| 天天看,天天做| 亚洲一本色码中文字幕| 国产午夜在线观看| 亚 欧 美 综合| 日本五区不卡| 淫荡少妇免费| 先锋音影AV| 日产操逼| 大香蕉综合| 91天天| 99成人| 亚洲激情深爱文学小说网站| 人人操,操人人| 免费网色网站| 国产91av在线播放| 久插综合| 三级精品三级在线观看| 国产免费大片| 午夜性生活av免费在线看| 狠狠狠狠狠干| 国产精品农村妇女| 九九热超碰| 精品少妇一区二区三区| 五月天社区| 91美女视频直播| 日韩在线观看字幕精品| 欧美激情亚洲情色| 91色久| 蜜汁欧美| 后X久久| 伊人国产成人av网站| 亚洲情色第一页| 久久久一区二区三区四区五区| 91操操| 久久女人| 欧美一二在线| 免费一级a毛片久久久久久鸭绿欲| 97色色国产视频| 草莓精品视频在线免费观看| 精品无码人妻一区二区免费蜜桃| 顶级丝袜熟女一区二区三区| 色香91| 99久久精品国产高潮| 国产AV天美传媒一区二区三区| 免费看久久久性性| 午夜传煤十二区精品| 日韩一区二区精品视频| 五月天激情网图片| 六月婷婷综合| 正宗无毛一线天嫩逼| 370p日韩欧美亚洲精品| 伊人991| 天天综合97| 成人看片网站| 91天美| 99re6久热只有精品6在线直播 | 99自拍视频在线| 国产精品网址| 男人天堂综合| 成视频在线观看免费看| 亚洲午夜精品久久久中文影院| 大地资源在线观看中文第二页| 国产av色网| 亚洲制服欧美另类内射| 神马麻豆福利院| 中文字幕丝袜人妻| 婷婷五月天伊人| 91久久久亚洲| 中文字幕诱惑制服人妻丝袜美丝袜美| 免费视频a级毛片免费视频| 91高潮| 欧美色图私拍91| 亚洲精品a人片在线观看视| 另类图片综合| 啊啊啊慢点| 日韩久久超碰色| 97国产高清视频在线观看| 精品人妻久久久| 日本99一区二区| 亚洲国产精品久久久久久久久久| 特级特黄一级毛片免费| 精品一区二区三区麻豆| 夜夜爽夜夜摸夜夜操免费视频| 久久久艹艹艹| 日本 情色 1区2区3区| 久久手机好看网站| 屌色在线97视频| 国产麻豆福利av在线播放| 精品欧美乱码久| 怡红院亚洲怡春院av| 18岁禁 茉莉成人久久| 黑人粗大V S日韩女优视频| 天天干天天干天天干| 青青草福利视频| 麻豆性爱视频在线播放| 日韩不卡a级视频专区| 国产精品久久久久9999小说| 激情图片伦理国产一区二区日韩| www久久国产精品| 亚洲和欧美裸体美女双飞视频| 亚洲九月丁香| 色婷婷国产精品一区在线观看| 精品高清一区二区三区三州| 国产精品亚洲一级av第二区| 欧美操逼熟女| 死我十八禁| 婷婷综合久久| 天天干夜夜操网| 午夜操一操| 蜜桃传媒视频第一区入口在线看| 600国产精品视频| 99999久久精| 少妇淫妇久久久久久久| 成人性交午夜免费片| 久久九色| 九月丁香婷婷色| 欧美大香蕉专区网| 玖玖97综合| 欧美狠狠操| 中文字幕AV片| 97操| 国产成人bd在线观看| 色9999日韩国产| 少妇六月天| 精品中文日韩字幕视频| 天天久久| 国产女性无套 免费观看| 久久精品国产精品亚洲艾通辽熟妇| 亚洲丝袜色| 加勒比日本在线| 国产精品日日摸天天碰| 国产精品久久99日日| 五月丁香色色网| 97色妞| 少妇久久久久久久久| 26uuu性物| 麻豆久久久久久久久丝袜| 国产后入清纯| 无码高清国产AV| 久久黄黄| 色香欲影| 天天爽天天操| 久久大香蕉97| 午夜男女爽爽爽在线视频| 亚洲欧美setu| 成人无码在线超碰网| 亚洲熟女国产综合另类| 中国91AV| 综合久久99| 伦在线97| 亚洲无码免费看| 色天欧美| 国产99久久99热这里只有精品15 | 欧美日韩不卡传媒| 亚洲熟女乱熟乱熟妇综合网二区| 亚洲天堂五月天国产| 射丝袜高跟鞋99| 乱伦熟妇一区二区| 亚洲AV无码久久精品蜜桃小说| 美女刺激久久国产欧美| 欧美狠狠| 久久九九久精品国产尤物|国产精品爽黄69天堂A片潘金莲,国产亚洲精品第一综合 | 精品少妇一区二区三区免费观看| 欧美人人天天网| 妇女一区二区三区| 天堂8在线新版官网| 激情综合五月天| 夜精品久无码| 老熟女乱伦一区| 国产AV超爽| 熟妇视频一区二区三区在线观看| 夜夜嗨绯色| 91狠狠综合久久久| 操逼日韩无码| 成熟熟女国产精品一区二区| 久久久极品| 欧美日韩免费专区在线| 亚洲日韩精品一区视频在线| 密乳视频在线| 欧美在线大香999| 婷婷8月天青娱乐| 大香蕉92| 欧美日韩少妇色情| 91人人爽人人爽人人人,gav福利视频导航,日韩欧美亚洲国产字幕四区 | 欧美视频一| av草草在线电影| 在线 亚洲 网爆 自拍| 久久欧美性爱视频| 日日夜夜精品| 国产在线综合福利网站| 97综合激情| 欧美天堂超碰97| 日韩欧美资源| 久久HD| 26uuu成人影片| 蜜臀99久久精品久久久久久| 操一区| 日日骚 av| 婷婷五月丁香五月| 九月婷婷| 亚洲 综合 欧美| 久久久国产亚洲精品系列| 久久超碰97| 超碰天天去日穴| 欧天美中出| 国产天天看| 一区二区精品更新提醒| 99啪啪| 老女人碰碰在线碰碰视频| 加勒比日本在线| 精品国产乱码久久久久久久久久毛片| 91n处女在线观看| 嗯嗯不要 视频| 色逼综合| 国产亚洲性生活视频播放| 蜜乳视频网站| 亚洲最大AV网| 99热精品在线观看| 一本一道人妻久久一区二区三区| 嗯啊不要在线观看嗯啊| 偷拍欧美综合| 国产精品在线网站| 日本不卡在线二区三区| 一区二区三区免费视频入口| 国产成人精品必看| 99色在线观看| 老司机免费视频在线91| 九九操久久国产免费视频| 狠狠色综合网| 天天看片麻豆| 91丝袜视频在线观看| 久艾草在线精品视频在线观看| 国产Aα| 日本 欧美 亚中文字幕| 国产精品suv一区| 在线一区| 少妇无码太爽| 99亚洲国产精品色一区二区三区| 男人的天堂久久狠| 免费看黄片现成| 久久性视频| 亚洲色图欧美另类在线| 日韩AC| 欧美第五页| 涩涩涩综合| 亚洲最大的黄色电影网站。| 97资源久久| 91精品微拍福利| 毛片久久| 肉动漫无遮挡h在线观看| 蜜桃狠狠色伊人亚洲综合网站| 97超碰影音| 91激情国产| 可乐操亚洲蜜911| 七月婷婷综合| 亚洲男人综合| 黄色性爱网网| 超碰97欧美在线| 精品十三区| 超碰九色| 亚洲本色精品一区二区久久| 国产白领连续中出在线观看| 西西美女视频网| 无码九九| 久久97超碰| 少妇被c 黄 免费观看| 国产午夜在线观看视频| 蜜桃久久久久久久久久久久| 亚洲最新中文字幕免费| 91精品操美女| 五月黑AⅤ| 国产伦精品| 啊啊好多水| 波多野42部无码喷潮在线观看| 伦理弟一页| 久操不卡视频| 中文AV制服乱伦| 国产一区二区久久| 超碰99在线| 国产强奸乱伦欧美| 伊人在线大香蕉视频久久| 国内自拍 日韩激情 99| 97超碰人人模人人拍人人| 亚洲情色在线| 99在线精品视频| 亚洲蜜乳av| 性一级黄色录像片网站导航| 欧美少妇色综合| 懂色AV一区二区三区| 午夜乱轮操逼视频免费看| 热热色综合网| 欧美日韩婷婷中文| 竹菊影视国产一区二区| 91中出| 尤物视频新赏网鲜网色诱网| 国产亚洲欧洲在线观看| www.狠狠操| 久操凹凸视频| 久久久精品中文字幕爱豆| 日本黄色精品| 天天爱综合网| 欧美,亚洲,日韩,v,天堂,手机在线观看 | 日han少妇无码| 麻豆人妻精品一区二区| 五月丁香激情综合| 久久一级无码精品毛片6| 中文操逼字幕| 97在线免费观看视频| AV女资源| 清纯唯美激情| 丰满人妻-区二区三区免费看| 综合情欲网| 激情文学小说一区二区| 麻豆色99999| 在线洲亚线| 国产乱不卡| 新怡红院| 97色碰| 91在线免费精品视频| 色综合av综合久久| 91P0RNY大屁股人妻| 成人性爱AV在线免费观看| 国产一区二区在线播放量| 国产视频一区二区三区在线免费观看 | 蜜桃av综合网发布| 综合大香蕉美。| 国产九月婷婷| 探花视频免费观看国产专区| 97超级欧美| 欧美日韩一区二区三区四区蜜桃| 欧美高清在线| 快点操死我| 国产福利影视| 亚洲性网| 五月天激情四射| 伊人一区二区三区| 成人综合色网| 亚洲色色探花| 欧美人妻少妇| 国产丝袜高跟美女av免费观看| 99这里只有精品| 蜜乳AV免费观看| 伦伦成年午夜免费视频| 色逼综合| 女优大全 - 91n| 色超碰综合| 曰韩欧美国产传媒麻豆第一区| 一级片在线观看高清无码| 97超碰精品| 日韩欧美女求操每天更新| 美腿丝袜高跟网免费视频免费视频| 天操天操夜操夜月月年年操操| 亚洲国产熟妇综合色专区| 精品无av| 97中文字幕一区| 手机av亚洲丝袜美腿日韩第一页二页| 欧洲中文字幕| 中文一区二区婷婷视频| 97色在线观看| 夫妻四区五区六区| 黄色AV影视| 91大学精品激情戏| 丁香五月影院| 五月天丁香| 亚洲综合激情五月久久| 99精品视频在线观看| 激情五月天婷婷| 婷婷色网| 日韩一级二级三级免费看完整版| 婷婷四五区| 亚洲天天在线| 免费的很黄很污的全部视频| 操高情无码| 久久久久久精| 330dv亚洲成年视频网| 国产Av超碰| julia中文字幕在线观看| 国人欧美精品一区二区| 东北老熟女| 亚洲综合激情五月久久| 69精品| 亚射在线| 91精品丝袜久久久久久| 五十路三区在线| 60秒免费小视频| 亚洲国产一区二区三区四区国产| 蜜臀99久久国产| 人人妻人人操人人乐| 91精品久久久| 蜜汁欧美| 青青欧洲黑| 人妻少妇色综合| 久久社区一区二区三区| 一本色道熟妇| 淫乱图区 | 日韩午夜精品一区二区三区电影| 九t超碰| 东北女人| 亚洲男人的天堂一区二区| 日韩欧美字幕亚洲一区二区 | 日韩黄片视频试看| 丰满人妻-区二区三区| 青青草玖玖爱| 国产偷仑| 婷婷五月天网| 亚洲国产麻豆一区二区三区| 亚洲美女av无码| 久9爱精品| 91美女看B| 色盈盈影院| 另类小说五月天| 图片区小说区| 日韩一级免费性爱| 国产69精品久久久久99尤物| 久久久少妇| 国产路线专区| 亚洲图片欧美| 视频一区二区免费在线| 特色a在线上| 亚洲欧美97| 欧美亚洲特P| 丝袜美腿丝袜| 中欧人妻丝袜中文字幕 | 久久久久9999| 丁香色婷婷| 色情成人五月天| 人妻人人操| 五月天婷婷基地| www.狠狠| 午夜久久一区二区无码中出| 国产高清不卡视频| 午夜乱轮操逼视频免费看| 亚射在线| 狠日操| 日韩欧美蜜桃精品久久中文字幕久久| 欧美日韩操逼嗦吊| 精品国产乱子伦一区二区三区,精品一| 国产伦精品一区二区三区在线观 | 国产精品色约约| 九九热免费视频| 一区二区三区免费视频入口| Aa东京男人的天堂| 欧美一级色| 亚洲大色堂| 超碰在线1234区| 91一区二匹| 懂色天天爱天天日天天射天天澡| 国产美女精品| 久7色| 国产麻豆福利av在线播放| 玖玖久久久| 一区二区不卡| 免费观看国产不卡av| 99综合网| 久湿久久| 中文日本免费高清| 人人手机欧洲亚洲国产人妻| 黄久在线| 国产黄色影片在线观看| 亚洲春色激情小说| 国产精品3| A级国产欧美激情在线| 丁香六月激情| 情色五月天就去干| 亚洲另类小说卡通动漫| 国产欧美日韩女同性恋ww喷水精品 | 一区麻豆 高清中文字幕| 久久东京热成人| 韩国黄片aaaa| 成人熟女视频一区二区三区| 午夜毛片亚洲精品片国产久久久| 人人爱操| 亚州性色| 一本久道久久综合狠狠爱| 不卡六六在线91| av日韩国产一区二区| 97AV在线免费观看| 欧美伊人久久综合网| 亚州精品丝袜-不卡成人免费| 视频不卡中文字幕| 青青草视频在线观看一区二区| 中文字幕精品探花视频| 无码一区二区三区四区五区六区七区八区九区十区视频 | 囯戸精品高潮呻吟旡码| 日本大香蕉| 爱av免费| 91亚洲人| 色色综合97| 口爆吞精在线观看| 久久人妻一区二区三区高清| 亚洲欧美国产成人综合不卡| 国产日韩中文字幕欧美| 精品国产一区二区三区av在线资源| 91欧美少妇| 久久久9视频| 国产综合日韩伦理| 亚洲性图91| 国产呦精品一区二区三区下载| 精品国产乱码久久久久久久| 色嘟嘟人妻天堂网| 性爱Av免费| 精品少妇一区二区| 国内精品不卡无毒99999| 久久黄片国产一区二区| 性九九九九九九| 9 7超碰在线免费观看| 99视频自拍| 一区二区免费电影久久| 欧美性爱一区二区三区| 大香蕉青青9| 亚洲 中文 女同| 99在线无码精品秘 入口黑人| 99综合免费视频| 亚洲欧洲精品视频发布| 无码不卡亚洲成?人片| 国产精选视频| 欧美亚洲清纯| 嗯嗯啊啊的视频| 日日夜夜噜| 黄色成品网站| 999热日韩精品| 亚洲www91| 99re只有精品| 国产成人AV麻豆| 色天使大香蕉| 天天弄欧美| 久久伊人在线五区| ′ !γ}丶。。久久精品欧美一区二区三区| 在线观看亚洲专区| 操逼操逼逼操操逼91 | www.99色| 懂色中文一区二区三区| 国产第12页| 黑人中出21连凳花野真衣| 神马麻豆福利院| 亚洲天堂中文字幕无码男同| 欧美色老汉| 99在线精品观看99| 人妻精品一区二区三区| 99热思思| 日韩视频中文字幕| 黄色污污污污污污网站| 九九九免费视频| 97超碰碰碰| V A在线| 91色伦综合| 天天综合91在线| 欧美超碰在线| 男女啊啊啊啊啊| 六月丁香啪啪啪| 无码78| 在线啊啊啊啊| 无码人妻精品一区二区三区99不卡| 久操大香蕉手机视频在线看| 国际精品久久久| 欧美一级特黄淫片在线观看| 日韩中文字幕2020| 亚洲高清无码AAA久久久精品| 国产后入清纯| 熟妇在线视频一区二区| dy888午夜老子影视达达兔 | 亚洲精品国产熟女| 能看的AV| 麻豆区久久久久亚| 午夜啪| 91精品黄在线观看| 国产精品午夜福利视频| 久草这里只有精品| 在线无码操| 日本女厕偷拍| 亚洲一区二区三区在线激情| A片 AV一级在线播放观看免费 | 日韩三级一区| 美女上床网站| 一区不卡在线观看av| 亚洲熟妇丝袜在线观看| 超碰99在线| 黄片不用下载在线观看| 久久久成人精品| 亚洲一区在线观看欧洲| 五月婷婷激情| 综合五月天| 制服乱伦| 综合亚洲网| 久久一区二区三区入口| 一级黄碟| 伊人激情五月天一区二区| 欧美少妇内射| 一区二区三区成人高清视频| 人人爽人人精品乱人伦AV| 国产成人拍国产亚洲精品| 91亚洲黑人| 亚洲天天综合| 精品.99999| 日韩欧洲操屄视频| 欧美色一二三| 国产成人手机视频激情| 日韩大香蕉精品在线视频| 在线国产福利网址导航| 国产精品久久久久久久久久久久久久久久 | 人人操人人色网| 99RE在线视频精品,这里只有精品| 成年男人的天堂| 青青草视频久久久久| 久久伊人在线五区| 亚洲熟女综合| 少妇精品久久久| 欧美超碰人妻97| 97香蕉网| 综合久久2017| 日韩在线地址一| 欧美精品久久久久久久久88| 欧美精品999| 黄色小说亚洲| 日韩综合97P| 自拍啪啪视频| 国产亚洲精品A在线观看下载| 欧美日韩精品一区二区三区高清| 国产激情av女片自拍| 丁香六月婷婷久久综合| 中国女人内射6XXXXX| 国产精品直播在线观看直播| 少妇精品久久| 狠狠色五月亚洲91| 超碰在线1234区| 97精品国产精品免费观看| 日本色色色视频| 色女99一级片在线观看| 亚洲人妻精品一区二区| 不卡一区二区日本视频| 涩爱AV在线| 亚洲精品91| 丁香成人五月天| 婷婷亚洲中文字幕在线| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 97精品在线视频| 中文字幕乱妇免费视频| 懂色Av一区二区三区| 清纯唯美亚洲综合| 欧美人黑A片无码免视费| 翔田千里无码一区| 人人玩人人添人人澡免费| 亚洲AV无码AV吞精久久久久 | 中文字幕日韩人妻视频一区二区三区交换夫妻| 人妻天天夜夜爽一区二区| 欧美黄色图片| 欧美日韩天堂| 欧美日韩亚洲天堂| 13小男生GAY自慰脱裤子| 人妻偷拍一区二区三区| 蜜臀AV网站| 日韩女优在线| 亚洲综合码| 蜜乳Av成人片网站| 偷拍欧美激情| 91在线一起| 国产精品ww久久| 亚洲制服欧美另类内射| 九九热九九热| 超碰综合97在线| 天天综合97| 狠狠色噜噜狠狠狠狠狠色综合久久 | 抽插无码高清一区| 亚洲欧洲美腿丝袜| 97久久超碰日韩精品| 日婷婷| 欧美专区在线| 五月天人妻综合| 午夜一级免费毛片| 屌色在线97视频| 中文字幕一二三av| 亚洲欧美综合区自拍另类| 操穴国产| 天天干18禁| 欧美性爱一级操| 强奸熟女一区二区三区| 免费a v| 97九色人妻| 亚91网| 久久性爱城| 午夜乱轮操逼视频免费看| 天天日骚逼熟女| 亚洲AV色图一区| 91黑丝露脚| 日本十八禁免费看污网站| 国产黑白丝在线| 天天干,夜夜爽| 亚洲第一狼人丝袜美女另类 | 丁香婷婷激情五月天无毒不卡 | 91婷婷| 午夜亚洲WWW湿好大| 欧美最婬乱婬爆婬牲视频| 久久、1234| 亚洲天堂电影精品一区| aaaa少妇高潮大片| 久久久久人妻二区精品叶可怜| 久久25| 狠狠中文字幕| 蜜桃视频啊啊啊啊| 国产精品岛国片在线观看| 亚洲女人毛茸茸91| 色九九九九久| 日韩成人无码| 欲香欲色天天天综合和网| 逼逼逼逼操操操操操操操操操午夜剧场| 超碰2017| 啊啊啊骚| 天天日熟妇| 国产日韩中文字幕欧美| 骚女高跟AV在线| 欧美一级专区免费大片| 日韩精品第3页| 禁片 高清 在线观看视频网站| 人人操人人搞人人草| 久久久精品一区二区| 久久直播国产| 欧美加勒比| 亚洲性少妇| 99热精品在线观看| 狼狼色丁香久久婷婷综合五月| 精品免费囯产一区二区三区| 亚洲 中文 女同| 日本在线激情一区二区三区| 国产欧美在线观看免费观看| 公司1区2区3区精产精| 亚洲天堂女优在线| 99精品在线| 国产女人与拘做受视频免费| 九七超碰| 94色色电影网| 美女黄色91| 天欧美在线| 激情黄色五月天| 久久仑合| 91 国产丝袜在线放观看| 六月天婷婷| 看一级黄色视频| 成人网站 免费观看| 翔田千里AⅤHD无码| 国产精品美女久久久久久网站| 人妻熟女一区二区在线视频| 成人资源中文字幕在线观看| 中文字幕av丝袜| 亚洲AV无码天美传媒一区| 国产高清不卡视频| 又摸又舔在线观看网站| 精品国产乱码久久久久A| 国产99 中文字幕日韩小视频| 久久男人精品| 草莓精品视频| 亚洲天堂久久| 一级久久性爱视频| wwwcaobibi| 亚洲1区| 妺妺跟我一起洗澡没忍住| 色综合网1| 激情四射婷婷四五月天| 哈哈操电影AV| 9999亚洲精品| 偷偷人人精品女女久久| 一级毛片电影免费看| 小说区 图片区色 综合区| 无码人妻精品一区二区三区99不卡| 无码高清少妇久久| 粉嫩不卡一区二区性爱| 五月天婷婷激情| 欧美激情片一区二区| 久久成人东京热人妻| 蜜臀99久久国产| 国产探花日韩援交| 五月丁香亭亭| 超碰 av 女人天堂| 狠久久| 人人操人人摸人人看人人插| 思思性爱| 中文字幕丝袜人妻| 大香交| 欧美中文字幕日韩在线| 欧美日韩国产高清在线一二三区 | 精品熟妇视频一区二区| 亚洲国产精品V?在线播放| 国产男女无套视频免费观看| 成人A片男人的天堂| 久欲AV| 国产精品自拍xxxx| 亚洲三级网址久久最新| 大香久久| 探花激情视频| 碰人碰碰人人开房人肉| 国产日韩精品无码去免费专区国产| 亚洲综合婷婷| 欧洲站一级二级三级h| 无码操逼网| 青青欧洲黑| 欧美性爱无码一区二区三区| 厕所偷拍在线| 老女人综合网| 国产夜夜艹| 亚洲日韩天堂| 九一屌逼| 激情天天视频| 青青草视频久久久久| 囯产精品久久久久久久久久梁医生| 99热在线观看| 天天综合网日韩| 97人妻色| 蜜臀AV秘一区翔田千里| 超碰98综合网| 国产原创剧情在线丝袜| 色婷婷A V一二三四区麻豆综合| 人人操人人大香蕉| 蜜臀久久久99久久久久| 人人乐大香蕉| 五十路六十路七十路熟婆| 日本熟妇精品九九| 天天天天操| 97操| 青青草国产盗摄一二三区| 日韩乱伦视频| 精品无码久久久久久久久果冻糖心| 蜜桃传媒一区二区亚洲| 亚洲97成人在线观看| 精人妻无码一区二区三区伊人直播| 天美麻花大全视频| 日韩无码一级黄色av片| 素人无码中文字幕| 欧美另类色| 亚洲欧洲国产综合av| 69精品| 亚洲国产福利视频| 9 7超碰在线免费观看| 色色色五月婷婷| 天天激情综合站| 香蕉99秘 一区精品蜜桃臀| 99re在线精品78| 久妇网| 动漫爆乳3D奶水一区在线观看 | 超碰在线91| 色香综合天天影视综合| 成人日本精品九区| 99精品在线观看| 高清国产av无码| 在线观看国产黄色| 日韩综合成人免费视频| 久久久久久精| 亚洲熟女综合一区二区| 欧美91网| 欧美日韩亚洲国产中文永久天天看 | 婷婷视频在线免费观看| 98一区二区精品| 天美麻花大全视频| 一区二区三区黄色片a| 久久成人国产精品| 久久狠狠色噜噜狠狠狠狠97| 人妻精品一区二区| 999热日韩精品| www男人天堂| 一区二区三区麻豆| 啊啊啊免费| 国产又粗又长的视频| 超碰97国产欧美| 超碰97色| 一类无码操逼视频| 国产精品自在线发布| 人人摸人人摸人人干| 不卡啪啪视频| 蜜色网色哟哟| 伊人伊人LD| 亚洲图片 激情小说| 欧美黑人168页欧美黑人167| 殴美色网| 国产精品一区二区亚洲人成毛片| 亚洲熟女性高潮久久久| 国产成人无码高清| www鬼畜国产男人的天堂|