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

基於 TCP 長連結的簡易 Client/Server 實作(Linux select 模型)

     編輯:關於C++

流式長連結架構設計與 Linux select 多路複用實作

在區域網路環境,頻繁建立/銷毀 Socket 開銷極大。採用長連結(持久連線)配合長度前綴協議,可實現高效雙向資料流傳輸。本文提供基於 select I/O 多路複用的完整 Client/Server 參考實作。

協議設計:長度前綴幀格式

+--------+------------------+
| 8 bytes|   Payload        |
| Length | (Length bytes)   |
+--------+------------------+
  • 固定 8 位元組長度欄位(ASCII 編碼,右對齊空白填充)
  • 接收端先讀 8 位元組解析長度,再精確讀取 Payload
  • 支援任意長度資料,自動處理 TCP 黏包/拆包

Server 端核心架構

// 關鍵資料結構
struct ClientInfo { std::string host; int port; };
std::map<int, ClientInfo> clients;  // fd -> 客戶端資訊

// select 事件迴圈
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(server_fd, &read_fds);

while (true) {
    int nfds = select(FD_SETSIZE, &read_fds, NULL, NULL, NULL);
    if (FD_ISSET(server_fd, &read_fds)) {
        // 接受新連線
        int client_fd = accept(...);
        FD_SET(client_fd, &read_fds);
        clients[client_fd] = {ip, port};
    } else {
        // 處理客戶端資料
        for (auto& [fd, info] : clients) {
            if (FD_ISSET(fd, &read_fds)) {
                handle_client(fd, info);
                break;  // 簡化:單執行緒一次處理一個
            }
        }
    }
}

資料收發核心邏輯

// 發送:組裝長度前綴 + 資料,確保完整寫入
std::string send_buf = fmt::format("{:08d}", payload.size()) + payload;
size_t sent = 0;
while (sent < send_buf.size()) {
    ssize_t n = write(fd, send_buf.data() + sent, send_buf.size() - sent);
    if (n <= 0) handle_error();
    sent += n;
}

// 接收:先讀 8 位元組長度,再按長度讀取
char len_buf[9];
if (recv(fd, len_buf, 8, 0) != 8) handle_disconnect();
len_buf[8] = '\0';
int payload_len = atoi(len_buf);

std::string payload;
while (payload.size() < payload_len) {
    char buf[1024];
    ssize_t n = recv(fd, buf, std::min(sizeof(buf), payload_len - payload.size()), 0);
    if (n <= 0) handle_disconnect();
    payload.append(buf, n);
}

Client 端關鍵流程

  1. 解析命令列參數(主機、埠、發送內容)
  2. 建立 Socket,connect 連線 Server
  3. 發送資料(含長度前綴)
  4. 接收回應(解析長度前綴)
  5. 關閉連線

編譯與執行

g++ server.cc -o server -std=c++11
g++ client.cc -o client -std=c++11

# 終端機 1
./server 7763

# 終端機 2
./client localhost 7763 "Hello Server"

優化方向

  • 使用 epoll (Linux) / kqueue (BSD/macOS) / IOCP (Windows) 替代 select,支援更高併發
  • 引入執行緒池或非同步 I/O (asio/libuv) 處理業務邏輯
  • 加入心跳機制偵測斷線
  • 實作 TLS 加密傳輸

完整原始碼結構

文章包含完整可編譯的 server.cc (260 行) 與 client.cc (169 行),涵蓋命令列解析、錯誤處理、緩衝區管理、優雅關閉等工程細節,適合網路程式設計入門參考。

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