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

TCP/IP 迭代服務器通信軟件設計:基於消息隊列的三進程架構詳解

     編輯:C 語言基礎

背景:並發 vs 迭代服務器

  • 並發服務器:守護進程監聽,fork 子進程處理每個連接。缺點:客戶機多時子進程數爆炸,拖垮效率。
  • 傳統迭代服務器:串行處理連接,無子進程開銷。缺點:每次通信前需建連,開銷大,不適合隨機數據/繁忙業務。

新型迭代服務器優勢

僅用 三個進程 即可與所有客戶機建立並持久保持連接,兼具低進程開銷與隨機訪問能力,適合客戶機多、業務繁忙場景。

連接建立流程

  1. 首個客戶機請求連接 → 守護進程建立初始連接 L0。
  2. 客戶機發送兩個端口號,守護進程將 IP+端口登記到共享內存,關閉 L0。
  3. 守護進程 fork 兩個通信子進程,從共享內存讀取客戶機信息,分別建立 L1(讀連接)和 L2(寫連接),將 socket handle 存入共享內存。
  4. 後續客戶機請求:守護進程僅登記信息到共享內存,不再創建子進程。
  5. 通信子進程大循環:
      a. 掃描共享內存新記錄 → 建立新連接。
      b. 輪詢所有 L1 讀 socket,有數據則讀取並標記來源記錄號。
      c. 另一子進程根據記錄號從共享內存取對應 L2 寫 socket,發送響應。

守護進程核心代碼片段

struct servent *sp;
struct sockaddr_in peeraddr_in, myaddr_in;
linkf = 0;
sp = getservbyname("tcp_server", "tcp");
ls = socket(AF_INET, SOCK_STREAM, 0);
myaddr_in.sin_addr.s_addr = INADDR_ANY;
myaddr_in.sin_port = sp->s_port;
bind(ls, &myaddr_in, sizeof(struct sockaddr_in));
listen(ls, 5);
qid3 = msgget(MSGKEY3, 0x1ff);
qid4 = msgget(MSGKEY4, 0x1ff);
signal(SIGCLD, SIG_IGN);  // 避免僵屍進程
setsockopt(s, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); // 避免 TIME_WAIT
setpgrp();
switch(fork()) {
    case -1: exit(1);
    case 0:  // Daemon
        for(;;) {
            s = accept(ls, &peeraddr_in, &addrlen);
            setsockopt(s, SOL_SOCKET, SO_LINGER, &linger, lingerlen);
            server();  // 處理初始連接登記
            close(s);
        }
    default:
        fprintf(stderr, "初始進程退出,守護進程監聽中...\n");
}

關鍵設計點

  • 消息隊列(msgget)實現進程間共享內存索引。
  • SO_LINGER 置 0 避免 TIME_WAIT 狀態積壓端口。
  • SIGCLD 忽略防止子進程成僵屍。
  • 服務器需在 /etc/services 登記公用端口:tcp_server 2000/tcp。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved