首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

epoll 邊緣觸發(ET)模式實戰:高性能 Echo 服務器完整範例

     編輯:關於C語言

為什麼選擇 Edge-Triggered?

在高併發網絡服務開發中,epoll 的邊緣觸發(ET)模式能顯著減少系統調用開銷。不同於水平觸發(LT)會持續通知就緒狀態,ET 僅在狀態發生變化時觸發一次。這要求開發者在 epoll_wait 返回後,必須循環讀寫直到該文件描述符的緩衝區耗盡(讀返回 EAGAIN 或字節數小於請求值)或寫滿為止。

核心代碼架構

本範例實現一個 Echo 服務器:收到客戶端數據後,將內容重複 REPEAT_NUM (20000) 次組裝成巨大回應包(約 400KB),專門驗證 EPOLLOUT 事件處理邏輯。關鍵點包括:

  • 所有 Socket 設置為非阻塞(O_NONBLOCK)
  • 監聽 Socket 掛載 EPOLLIN | EPOLLET
  • 客戶端 Socket 同時掛載 EPOLLIN | EPOLLOUT | EPOLLET,避免後續 epoll_ctl 修改事件開銷
  • 全局緩衝區 g_out_buf 記錄待發送數據、偏移量與長度,配合 g_has_write_buf 標誌實現分片發送

關鍵邏輯:EPOLLOUT 分片發送

// 發送邏輯:嘗試寫入剩餘數據,遇到 EAGAIN 則保留狀態等待下一次 EPOLLOUT
int write_out_buf(int fd, char *out_buf, int buf_len, int offset) {
    int snd_len = write(fd, out_buf + offset, buf_len - offset);
    // ... 循環處理短寫與 EAGAIN ...
    return snd_len;
}

// EPOLLOUT 事件處理
else if (evs[i].events & EPOLLOUT) {
    clientFd = evs[i].data.fd;
    if (g_has_write_buf) {
        g_out_buf_offset += write_out_buf(clientFd, g_out_buf, g_out_buf_len, g_out_buf_offset);
        if (g_out_buf_offset == g_out_buf_len) g_has_write_buf = 0;
    }
}

測試驗證

配套 Perl 客戶端發送 10 字節測試數據,服務器端日誌清晰展示:

  1. epollin 讀取 10 字節 → 觸發 process_write 組裝 408890 字節回應
  2. 首次 write 僅發送 65536 字節(Socket 發送緩衝區滿)→ 觸發 EAGAIN
  3. 後續 5 次 epollout 事件分片發送剩餘數據,最終完成 408890 字節全量發送
  4. 客戶端關閉連接,服務器正確清理資源

工程啟示

此範例完整呈現 ET 模式下「讀寫循環 + 狀態機式分片發送」的標準範式,適合作為高性能網絡庫的基礎參考。代碼在 Linux 環境編譯運行,歡迎實測調優。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved