最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于C++的UDP網(wǎng)絡(luò)通信系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)詳解

 更新時(shí)間:2025年12月13日 11:26:38   作者:福爾摩斯張  
在網(wǎng)絡(luò)編程領(lǐng)域,UDP作為一種無(wú)連接的傳輸層協(xié)議,以其高效、低延遲的特性在實(shí)時(shí)性要求高的應(yīng)用場(chǎng)景中占據(jù)重要地位,下面我們就來(lái)看看如何從零開(kāi)始構(gòu)建一個(gè)完整的UDP通信系統(tǒng)吧

前言

在網(wǎng)絡(luò)編程領(lǐng)域,UDP(User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)作為一種無(wú)連接的傳輸層協(xié)議,以其高效、低延遲的特性在實(shí)時(shí)性要求高的應(yīng)用場(chǎng)景中占據(jù)重要地位。與TCP協(xié)議相比,UDP不需要建立連接,不保證數(shù)據(jù)包的順序和可靠性,但正是這種"輕量級(jí)"特性使其在視頻流、在線游戲、DNS查詢等領(lǐng)域得到廣泛應(yīng)用。

本文將深入探討如何從零開(kāi)始構(gòu)建一個(gè)完整的UDP通信系統(tǒng),涵蓋服務(wù)器端、客戶端的設(shè)計(jì)與實(shí)現(xiàn),包括套接字編程的核心概念、關(guān)鍵系統(tǒng)調(diào)用、錯(cuò)誤處理機(jī)制以及實(shí)際應(yīng)用中的注意事項(xiàng)。通過(guò)本文的學(xué)習(xí),讀者不僅能夠掌握UDP網(wǎng)絡(luò)編程的基本技能,還能深入理解網(wǎng)絡(luò)通信的底層原理。

本文實(shí)現(xiàn)的UDP通信系統(tǒng)具有以下特點(diǎn):

  • 完整的服務(wù)器/客戶端架構(gòu)
  • 詳細(xì)的錯(cuò)誤處理和日志記錄
  • 可配置的服務(wù)器參數(shù)
  • 跨平臺(tái)兼容性考慮
  • 豐富的代碼示例和詳細(xì)注釋

一、UDP服務(wù)器UdpServer.hpp

1.1 基本框架設(shè)計(jì)

UDP服務(wù)器的設(shè)計(jì)需要遵循模塊化、可擴(kuò)展的原則。我們將服務(wù)器封裝為一個(gè)類,包含初始化、運(yùn)行和清理等基本功能。

#ifndef UDPSERVER_HPP
#define UDPSERVER_HPP

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <thread>
#include <vector>
#include <memory>
#include <atomic>
#include <functional>
#include "Log.hpp"

class UdpServer {
private:
    int port_;                      // 服務(wù)器端口
    int sockfd_;                    // 套接字描述符
    std::atomic<bool> is_running_; // 服務(wù)器運(yùn)行狀態(tài)
    struct sockaddr_in server_addr_; // 服務(wù)器地址結(jié)構(gòu)
    struct sockaddr_in client_addr_; // 客戶端地址結(jié)構(gòu)
    socklen_t client_addr_len_;     // 客戶端地址長(zhǎng)度
    
    // 服務(wù)器配置參數(shù)
    size_t buffer_size_;           // 緩沖區(qū)大小
    int timeout_sec_;              // 接收超時(shí)時(shí)間(秒)
    int timeout_usec_;             // 接收超時(shí)時(shí)間(微秒)
    bool reuse_addr_;              // 是否重用地址
    
public:
    // 構(gòu)造函數(shù)
    explicit UdpServer(int port = 8080);
    
    // 析構(gòu)函數(shù)
    ~UdpServer();
    
    // 禁止拷貝構(gòu)造和賦值
    UdpServer(const UdpServer&) = delete;
    UdpServer& operator=(const UdpServer&) = delete;
    
    // 初始化服務(wù)器
    bool Init();
    
    // 運(yùn)行服務(wù)器
    void Run();
    
    // 停止服務(wù)器
    void Stop();
    
    // 設(shè)置配置參數(shù)
    void SetBufferSize(size_t size) { buffer_size_ = size; }
    void SetTimeout(int sec, int usec = 0) { 
        timeout_sec_ = sec; 
        timeout_usec_ = usec; 
    }
    void SetReuseAddr(bool reuse) { reuse_addr_ = reuse; }
    
private:
    // 創(chuàng)建套接字
    bool CreateSocket();
    
    // 綁定地址
    bool BindAddress();
    
    // 設(shè)置套接字選項(xiàng)
    bool SetSocketOptions();
    
    // 處理接收到的數(shù)據(jù)
    virtual void ProcessData(const char* data, ssize_t len, 
                            const struct sockaddr_in& client_addr);
    
    // 發(fā)送響應(yīng)
    bool SendResponse(const char* data, ssize_t len, 
                     const struct sockaddr_in& client_addr);
    
    // 清理資源
    void Cleanup();
};

#endif // UDPSERVER_HPP

1.2 初始化函數(shù)Init詳解

初始化函數(shù)是服務(wù)器啟動(dòng)的第一步,它負(fù)責(zé)套接字創(chuàng)建、地址綁定和選項(xiàng)設(shè)置等關(guān)鍵操作。

bool UdpServer::Init() {
    // 1. 創(chuàng)建日志實(shí)例
    Logger::Instance().Init("udp_server.log", LogLevel::INFO);
    LOG_INFO("Starting UDP server initialization...");
    
    // 2. 創(chuàng)建套接字
    if (!CreateSocket()) {
        LOG_ERROR("Failed to create socket");
        return false;
    }
    
    // 3. 設(shè)置套接字選項(xiàng)
    if (!SetSocketOptions()) {
        LOG_ERROR("Failed to set socket options");
        close(sockfd_);
        return false;
    }
    
    // 4. 綁定地址
    if (!BindAddress()) {
        LOG_ERROR("Failed to bind address");
        close(sockfd_);
        return false;
    }
    
    // 5. 初始化客戶端地址結(jié)構(gòu)
    memset(&client_addr_, 0, sizeof(client_addr_));
    client_addr_len_ = sizeof(client_addr_);
    
    LOG_INFO("UDP server initialized successfully on port %d", port_);
    LOG_INFO("Buffer size: %zu bytes", buffer_size_);
    LOG_INFO("Timeout: %d seconds %d microseconds", timeout_sec_, timeout_usec_);
    
    return true;
}

bool UdpServer::CreateSocket() {
    // 使用AF_INET表示IPv4,SOCK_DGRAM表示UDP協(xié)議
    sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd_ < 0) {
        LOG_ERROR("Socket creation failed: %s", strerror(errno));
        return false;
    }
    
    LOG_DEBUG("Socket created successfully, fd: %d", sockfd_);
    return true;
}

bool UdpServer::SetSocketOptions() {
    int optval = 1;
    
    // 設(shè)置地址重用選項(xiàng),避免"Address already in use"錯(cuò)誤
    if (reuse_addr_) {
        if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, 
                      &optval, sizeof(optval)) < 0) {
            LOG_WARN("Failed to set SO_REUSEADDR: %s", strerror(errno));
            // 注意:這不是致命錯(cuò)誤,可以繼續(xù)運(yùn)行
        } else {
            LOG_DEBUG("SO_REUSEADDR set successfully");
        }
    }
    
    // 設(shè)置接收超時(shí)
    if (timeout_sec_ > 0 || timeout_usec_ > 0) {
        struct timeval tv;
        tv.tv_sec = timeout_sec_;
        tv.tv_usec = timeout_usec_;
        
        if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVTIMEO, 
                      &tv, sizeof(tv)) < 0) {
            LOG_WARN("Failed to set receive timeout: %s", strerror(errno));
        } else {
            LOG_DEBUG("Receive timeout set to %ld.%06ld seconds", 
                     tv.tv_sec, tv.tv_usec);
        }
    }
    
    // 設(shè)置發(fā)送緩沖區(qū)大小
    int send_buf_size = 1024 * 1024; // 1MB
    if (setsockopt(sockfd_, SOL_SOCKET, SO_SNDBUF, 
                  &send_buf_size, sizeof(send_buf_size)) < 0) {
        LOG_WARN("Failed to set send buffer size: %s", strerror(errno));
    }
    
    // 設(shè)置接收緩沖區(qū)大小
    int recv_buf_size = 1024 * 1024; // 1MB
    if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, 
                  &recv_buf_size, sizeof(recv_buf_size)) < 0) {
        LOG_WARN("Failed to set receive buffer size: %s", strerror(errno));
    }
    
    return true;
}

bool UdpServer::BindAddress() {
    // 初始化服務(wù)器地址結(jié)構(gòu)
    memset(&server_addr_, 0, sizeof(server_addr_));
    
    // 設(shè)置地址族為IPv4
    server_addr_.sin_family = AF_INET;
    
    // 設(shè)置端口,使用htons進(jìn)行字節(jié)序轉(zhuǎn)換
    server_addr_.sin_port = htons(port_);
    
    // 設(shè)置IP地址為INADDR_ANY,表示監(jiān)聽(tīng)所有網(wǎng)絡(luò)接口
    server_addr_.sin_addr.s_addr = htonl(INADDR_ANY);
    
    // 綁定套接字到指定地址和端口
    if (bind(sockfd_, (struct sockaddr*)&server_addr_, 
             sizeof(server_addr_)) < 0) {
        LOG_ERROR("Bind failed on port %d: %s", port_, strerror(errno));
        return false;
    }
    
    // 獲取實(shí)際綁定的地址信息
    struct sockaddr_in actual_addr;
    socklen_t actual_len = sizeof(actual_addr);
    if (getsockname(sockfd_, (struct sockaddr*)&actual_addr, &actual_len) == 0) {
        char ip_str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &actual_addr.sin_addr, ip_str, sizeof(ip_str));
        LOG_INFO("Server bound to %s:%d", ip_str, ntohs(actual_addr.sin_port));
    }
    
    return true;
}

1.3 關(guān)鍵系統(tǒng)調(diào)用詳解

1.inet_addr函數(shù)

inet_addr函數(shù)用于將點(diǎn)分十進(jìn)制表示的IPv4地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序的32位整數(shù)。雖然本文代碼中使用的是inet_pton(更安全的版本),但理解inet_addr仍然很重要。

// inet_addr的使用示例
const char* ip_str = "192.168.1.100";
in_addr_t addr = inet_addr(ip_str);
if (addr == INADDR_NONE) {
    LOG_ERROR("Invalid IP address: %s", ip_str);
} else {
    LOG_DEBUG("IP %s converted to network byte order: 0x%08x", 
             ip_str, addr);
    
    // 轉(zhuǎn)換回點(diǎn)分十進(jìn)制格式
    struct in_addr addr_struct;
    addr_struct.s_addr = addr;
    char* ip_str_back = inet_ntoa(addr_struct);
    LOG_DEBUG("Converted back to string: %s", ip_str_back);
}

// 現(xiàn)代推薦使用inet_pton(更安全,支持IPv6)
struct sockaddr_in addr;
if (inet_pton(AF_INET, ip_str, &addr.sin_addr) <= 0) {
    LOG_ERROR("Invalid IP address format: %s", ip_str);
}

2.bzero和memset函數(shù)

bzero是BSD系統(tǒng)中用于將內(nèi)存區(qū)域清零的函數(shù),而memset是標(biāo)準(zhǔn)C庫(kù)函數(shù),功能更通用。

// bzero的使用(傳統(tǒng)方式)
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));  // 將整個(gè)結(jié)構(gòu)體清零

// memset的等效用法
memset(&addr, 0, sizeof(addr));  // 更標(biāo)準(zhǔn)的做法

// memset的更多用途
char buffer[1024];
// 全部設(shè)置為0
memset(buffer, 0, sizeof(buffer));
// 全部設(shè)置為特定值
memset(buffer, 'A', sizeof(buffer));
// 部分設(shè)置
memset(buffer, 0, 100);  // 只清空前100字節(jié)

// 性能比較:對(duì)于大內(nèi)存塊,memset通常經(jīng)過(guò)優(yōu)化,性能更好

1.4 服務(wù)器運(yùn)行函數(shù)Run

Run函數(shù)是服務(wù)器的核心,負(fù)責(zé)循環(huán)接收客戶端請(qǐng)求并處理。

void UdpServer::Run() {
    if (sockfd_ < 0) {
        LOG_ERROR("Cannot run server: socket not initialized");
        return;
    }
    
    is_running_ = true;
    LOG_INFO("UDP server started, waiting for connections...");
    
    // 分配接收緩沖區(qū)
    std::vector<char> buffer(buffer_size_);
    
    // 主循環(huán)
    while (is_running_) {
        // 重置客戶端地址信息
        memset(&client_addr_, 0, sizeof(client_addr_));
        client_addr_len_ = sizeof(client_addr_);
        
        // 接收數(shù)據(jù)
        ssize_t recv_len = recvfrom(sockfd_, buffer.data(), buffer.size() - 1,
                                    0, (struct sockaddr*)&client_addr_, 
                                    &client_addr_len_);
        
        if (recv_len < 0) {
            // 處理接收錯(cuò)誤
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                // 超時(shí),繼續(xù)循環(huán)
                continue;
            } else if (errno == EINTR) {
                // 被信號(hào)中斷
                LOG_DEBUG("recvfrom interrupted by signal");
                continue;
            } else {
                LOG_ERROR("recvfrom failed: %s", strerror(errno));
                break;
            }
        } else if (recv_len == 0) {
            // UDP中recvfrom返回0表示收到了0字節(jié)的數(shù)據(jù)包
            LOG_DEBUG("Received empty datagram");
            continue;
        }
        
        // 確保字符串以null結(jié)尾
        buffer[recv_len] = '\0';
        
        // 獲取客戶端信息
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr_.sin_addr, 
                 client_ip, sizeof(client_ip));
        uint16_t client_port = ntohs(client_addr_.sin_port);
        
        LOG_DEBUG("Received %zd bytes from %s:%d", 
                 recv_len, client_ip, client_port);
        LOG_DEBUG("Data: %s", buffer.data());
        
        // 處理數(shù)據(jù)
        ProcessData(buffer.data(), recv_len, client_addr_);
    }
    
    LOG_INFO("UDP server stopped");
    Cleanup();
}

void UdpServer::ProcessData(const char* data, ssize_t len, 
                           const struct sockaddr_in& client_addr) {
    // 默認(rèn)實(shí)現(xiàn):原樣返回?cái)?shù)據(jù)(echo服務(wù)器)
    LOG_DEBUG("Processing %zd bytes of data", len);
    
    // 構(gòu)造響應(yīng)
    std::string response = "Server received: ";
    response.append(data, len);
    
    // 發(fā)送響應(yīng)
    if (!SendResponse(response.c_str(), response.length(), client_addr)) {
        LOG_ERROR("Failed to send response to client");
    }
}

bool UdpServer::SendResponse(const char* data, ssize_t len,
                            const struct sockaddr_in& client_addr) {
    if (len <= 0) {
        LOG_WARN("Attempting to send empty data");
        return true;  // 空數(shù)據(jù)發(fā)送"成功"
    }
    
    // 發(fā)送數(shù)據(jù)
    ssize_t sent_len = sendto(sockfd_, data, len, 0,
                             (const struct sockaddr*)&client_addr,
                             sizeof(client_addr));
    
    if (sent_len < 0) {
        LOG_ERROR("sendto failed: %s", strerror(errno));
        return false;
    }
    
    if (sent_len != len) {
        LOG_WARN("Partial send: %zd of %zd bytes sent", sent_len, len);
    }
    
    // 獲取客戶端信息用于日志
    char client_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));
    uint16_t client_port = ntohs(client_addr.sin_port);
    
    LOG_DEBUG("Sent %zd bytes to %s:%d", sent_len, client_ip, client_port);
    return true;
}

1.5 recvfrom和sendto函數(shù)深度解析

1.recvfrom函數(shù)

recvfrom是UDP接收數(shù)據(jù)的核心函數(shù),它不僅可以接收數(shù)據(jù),還能獲取發(fā)送者的地址信息。

/**
 * recvfrom函數(shù)原型:
 * ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
 *                  struct sockaddr *src_addr, socklen_t *addrlen);
 * 
 * 參數(shù)說(shuō)明:
 * - sockfd: 套接字描述符
 * - buf: 接收緩沖區(qū)
 * - len: 緩沖區(qū)大小
 * - flags: 標(biāo)志位,常用值:
 *     * 0: 默認(rèn)行為
 *     * MSG_WAITALL: 等待所有數(shù)據(jù)(對(duì)UDP通常無(wú)效)
 *     * MSG_DONTWAIT: 非阻塞模式
 *     * MSG_PEEK: 查看數(shù)據(jù)但不從緩沖區(qū)移除
 * - src_addr: 發(fā)送方地址(輸出參數(shù))
 * - addrlen: 地址長(zhǎng)度(輸入輸出參數(shù))
 * 
 * 返回值:
 * - 成功:接收到的字節(jié)數(shù)
 * - 失敗:-1,設(shè)置errno
 * - 連接關(guān)閉(TCP)或空數(shù)據(jù)包(UDP):0
 */

// recvfrom的完整示例
void ReceiveExample(int sockfd) {
    struct sockaddr_in client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[4096];
    
    // 設(shè)置接收超時(shí)
    struct timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    
    // 接收數(shù)據(jù)
    ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer) - 1,
                               MSG_DONTWAIT,  // 非阻塞模式
                               (struct sockaddr*)&client_addr, &addr_len);
    
    if (recv_len > 0) {
        buffer[recv_len] = '\0';
        
        // 獲取客戶端信息
        char ip_str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr.sin_addr, ip_str, sizeof(ip_str));
        uint16_t port = ntohs(client_addr.sin_port);
        
        LOG_INFO("Received from %s:%d: %s", ip_str, port, buffer);
        
        // 處理不同的消息類型
        ProcessMessage(buffer, recv_len, client_addr);
    } else if (recv_len == 0) {
        LOG_DEBUG("Received empty datagram");
    } else {
        // 錯(cuò)誤處理
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            LOG_DEBUG("No data available (non-blocking)");
        } else if (errno == EINTR) {
            LOG_DEBUG("Interrupted by signal");
        } else {
            LOG_ERROR("Receive error: %s", strerror(errno));
        }
    }
}

// 處理不同類型的消息
void ProcessMessage(const char* data, ssize_t len, 
                   const struct sockaddr_in& client_addr) {
    // 簡(jiǎn)單的協(xié)議處理示例
    if (len >= 4 && strncmp(data, "PING", 4) == 0) {
        LOG_DEBUG("Received PING request");
        SendResponse("PONG", 4, client_addr);
    } else if (len >= 4 && strncmp(data, "TIME", 4) == 0) {
        time_t now = time(nullptr);
        std::string time_str = ctime(&now);
        SendResponse(time_str.c_str(), time_str.length(), client_addr);
    } else if (len >= 7 && strncmp(data, "ECHO ", 5) == 0) {
        // 回顯消息內(nèi)容
        SendResponse(data + 5, len - 5, client_addr);
    } else {
        std::string response = "Unknown command: ";
        response.append(data, len);
        SendResponse(response.c_str(), response.length(), client_addr);
    }
}

2.sendto函數(shù)

sendto是UDP發(fā)送數(shù)據(jù)的核心函數(shù),用于向指定地址發(fā)送數(shù)據(jù)報(bào)。

/**
 * sendto函數(shù)原型:
 * ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
 *                const struct sockaddr *dest_addr, socklen_t addrlen);
 * 
 * 參數(shù)說(shuō)明:
 * - sockfd: 套接字描述符
 * - buf: 發(fā)送緩沖區(qū)
 * - len: 要發(fā)送的數(shù)據(jù)長(zhǎng)度
 * - flags: 標(biāo)志位,常用值:
 *     * 0: 默認(rèn)行為
 *     * MSG_DONTWAIT: 非阻塞模式
 *     * MSG_CONFIRM: 確認(rèn)路由有效(Linux特有)
 *     * MSG_MORE: 還有更多數(shù)據(jù)要發(fā)送
 * - dest_addr: 目標(biāo)地址
 * - addrlen: 地址長(zhǎng)度
 * 
 * 返回值:
 * - 成功:發(fā)送的字節(jié)數(shù)(可能小于len)
 * - 失?。?1,設(shè)置errno
 */

// sendto的完整示例
bool SendData(int sockfd, const void* data, size_t len,
             const struct sockaddr_in& dest_addr) {
    if (len == 0) {
        LOG_WARN("Attempting to send zero-length data");
        return true;
    }
    
    // 檢查數(shù)據(jù)包大小(UDP最大約64KB,實(shí)際建議小于1500字節(jié)避免分片)
    if (len > 65507) {  // 65535 - 20(IP頭) - 8(UDP頭)
        LOG_ERROR("Datagram too large: %zu bytes (max: 65507)", len);
        return false;
    }
    
    if (len > 1400) {
        LOG_WARN("Large datagram: %zu bytes (may be fragmented)", len);
    }
    
    // 分塊發(fā)送大數(shù)據(jù)(如果需要)
    const size_t MAX_CHUNK = 1400;  // 避免IP分片的推薦大小
    size_t total_sent = 0;
    
    while (total_sent < len) {
        size_t chunk_size = std::min(MAX_CHUNK, len - total_sent);
        const char* chunk_start = static_cast<const char*>(data) + total_sent;
        
        ssize_t sent = sendto(sockfd, chunk_start, chunk_size, 0,
                             (const struct sockaddr*)&dest_addr,
                             sizeof(dest_addr));
        
        if (sent < 0) {
            LOG_ERROR("Failed to send chunk: %s (sent %zu/%zu bytes)",
                     strerror(errno), total_sent, len);
            return false;
        }
        
        total_sent += sent;
        
        // 添加小延遲避免擁塞
        if (chunk_size == MAX_CHUNK && total_sent < len) {
            usleep(1000);  // 1ms延遲
        }
    }
    
    LOG_DEBUG("Successfully sent %zu bytes to %s:%d",
             total_sent,
             inet_ntoa(dest_addr.sin_addr),
             ntohs(dest_addr.sin_port));
    
    return true;
}

// 發(fā)送不同類型的消息
void SendVariousMessages(int sockfd, const struct sockaddr_in& dest_addr) {
    // 1. 發(fā)送字符串
    const char* text = "Hello, UDP Server!";
    SendData(sockfd, text, strlen(text), dest_addr);
    
    // 2. 發(fā)送二進(jìn)制數(shù)據(jù)
    struct BinaryData {
        uint32_t magic;
        uint16_t version;
        uint8_t type;
        uint8_t data[256];
    } binary_msg;
    
    binary_msg.magic = htonl(0xDEADBEEF);
    binary_msg.version = htons(1);
    binary_msg.type = 0x42;
    memset(binary_msg.data, 0xAA, sizeof(binary_msg.data));
    
    SendData(sockfd, &binary_msg, sizeof(binary_msg), dest_addr);
    
    // 3. 發(fā)送結(jié)構(gòu)化數(shù)據(jù)(JSON格式)
    std::string json_msg = R"({
        "command": "update",
        "timestamp": )" + std::to_string(time(nullptr)) + R"(,
        "data": {"temperature": 23.5, "humidity": 65.2}
    })";
    
    SendData(sockfd, json_msg.c_str(), json_msg.length(), dest_addr);
    
    // 4. 發(fā)送帶序列號(hào)的消息
    for (int i = 0; i < 10; i++) {
        std::string seq_msg = "Message #" + std::to_string(i);
        SendData(sockfd, seq_msg.c_str(), seq_msg.length(), dest_addr);
        
        // 添加延遲
        usleep(100000);  // 100ms
    }
}

1.6 高級(jí)功能:多線程處理和連接管理

對(duì)于高性能UDP服務(wù)器,我們需要考慮多線程處理和客戶端連接管理。

// 擴(kuò)展UdpServer類,添加多線程支持
class AdvancedUdpServer : public UdpServer {
private:
    std::vector<std::thread> worker_threads_;
    std::atomic<int> thread_count_;
    int max_workers_;
    
    // 線程池和工作隊(duì)列
    std::queue<std::pair<std::vector<char>, sockaddr_in>> task_queue_;
    std::mutex queue_mutex_;
    std::condition_variable queue_cv_;
    
public:
    AdvancedUdpServer(int port = 8080, int max_workers = 4)
        : UdpServer(port), max_workers_(max_workers), thread_count_(0) {}
    
    ~AdvancedUdpServer() {
        Stop();
    }
    
    bool Init() override {
        if (!UdpServer::Init()) {
            return false;
        }
        
        // 創(chuàng)建工作線程
        for (int i = 0; i < max_workers_; i++) {
            worker_threads_.emplace_back(&AdvancedUdpServer::WorkerThread, this, i);
        }
        
        LOG_INFO("Started %d worker threads", max_workers_);
        return true;
    }
    
    void Run() override {
        if (sockfd_ < 0) {
            LOG_ERROR("Socket not initialized");
            return;
        }
        
        is_running_ = true;
        LOG_INFO("Advanced UDP server started on port %d", port_);
        
        std::vector<char> buffer(buffer_size_);
        
        while (is_running_) {
            struct sockaddr_in client_addr;
            socklen_t addr_len = sizeof(client_addr);
            
            // 接收數(shù)據(jù)
            ssize_t recv_len = recvfrom(sockfd_, buffer.data(), 
                                       buffer.size() - 1, 0,
                                       (struct sockaddr*)&client_addr, 
                                       &addr_len);
            
            if (recv_len < 0) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    continue;
                } else if (errno == EINTR) {
                    continue;
                } else {
                    LOG_ERROR("Receive error: %s", strerror(errno));
                    break;
                }
            }
            
            if (recv_len > 0) {
                buffer[recv_len] = '\0';
                
                // 將任務(wù)加入隊(duì)列
                {
                    std::lock_guard<std::mutex> lock(queue_mutex_);
                    task_queue_.emplace(
                        std::vector<char>(buffer.begin(), buffer.begin() + recv_len),
                        client_addr
                    );
                }
                
                // 通知工作線程
                queue_cv_.notify_one();
                
                // 獲取統(tǒng)計(jì)信息
                if (task_queue_.size() > 10) {
                    LOG_WARN("Task queue size: %zu", task_queue_.size());
                }
            }
        }
        
        // 通知所有工作線程退出
        queue_cv_.notify_all();
        
        // 等待所有線程結(jié)束
        for (auto& thread : worker_threads_) {
            if (thread.joinable()) {
                thread.join();
            }
        }
        
        LOG_INFO("Advanced UDP server stopped");
        Cleanup();
    }
    
private:
    void WorkerThread(int thread_id) {
        thread_count_++;
        LOG_DEBUG("Worker thread %d started", thread_id);
        
        while (is_running_) {
            std::pair<std::vector<char>, sockaddr_in> task;
            
            {
                std::unique_lock<std::mutex> lock(queue_mutex_);
                queue_cv_.wait(lock, [this]() {
                    return !task_queue_.empty() || !is_running_;
                });
                
                if (!is_running_ && task_queue_.empty()) {
                    break;
                }
                
                if (!task_queue_.empty()) {
                    task = std::move(task_queue_.front());
                    task_queue_.pop();
                } else {
                    continue;
                }
            }
            
            // 處理任務(wù)
            ProcessTask(task.first, task.second, thread_id);
        }
        
        thread_count_--;
        LOG_DEBUG("Worker thread %d stopped", thread_id);
    }
    
    void ProcessTask(const std::vector<char>& data,
                    const sockaddr_in& client_addr,
                    int thread_id) {
        // 獲取客戶端信息
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr.sin_addr, 
                 client_ip, sizeof(client_ip));
        uint16_t client_port = ntohs(client_addr.sin_port);
        
        LOG_DEBUG("Thread %d processing %zu bytes from %s:%d",
                 thread_id, data.size(), client_ip, client_port);
        
        // 模擬處理時(shí)間
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        
        // 處理數(shù)據(jù)
        std::string response = "Thread " + std::to_string(thread_id) +
                              " processed: " + std::string(data.begin(), data.end());
        
        SendResponse(response.c_str(), response.length(), client_addr);
    }
};

// 連接管理類
class ConnectionManager {
private:
    struct ClientInfo {
        sockaddr_in address;
        time_t last_activity;
        uint64_t packet_count;
        uint64_t total_bytes;
        
        ClientInfo(const sockaddr_in& addr) 
            : address(addr), last_activity(time(nullptr)), 
              packet_count(0), total_bytes(0) {}
    };
    
    std::unordered_map<std::string, ClientInfo> clients_;
    std::mutex clients_mutex_;
    time_t cleanup_interval_;
    
public:
    ConnectionManager(time_t cleanup_interval = 300)  // 5分鐘
        : cleanup_interval_(cleanup_interval) {}
    
    // 更新客戶端活動(dòng)
    void UpdateClient(const sockaddr_in& addr, size_t bytes) {
        std::string key = GetClientKey(addr);
        
        std::lock_guard<std::mutex> lock(clients_mutex_);
        
        auto it = clients_.find(key);
        if (it == clients_.end()) {
            // 新客戶端
            clients_.emplace(key, ClientInfo(addr));
            it = clients_.find(key);
            
            char ip_str[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &addr.sin_addr, ip_str, sizeof(ip_str));
            LOG_INFO("New client connected: %s:%d", 
                    ip_str, ntohs(addr.sin_port));
        }
        
        // 更新統(tǒng)計(jì)信息
        it->second.last_activity = time(nullptr);
        it->second.packet_count++;
        it->second.total_bytes += bytes;
    }
    
    // 清理不活躍的連接
    void CleanupInactiveClients() {
        time_t now = time(nullptr);
        std::vector<std::string> to_remove;
        
        {
            std::lock_guard<std::mutex> lock(clients_mutex_);
            
            for (const auto& pair : clients_) {
                if (now - pair.second.last_activity > cleanup_interval_) {
                    to_remove.push_back(pair.first);
                }
            }
            
            for (const auto& key : to_remove) {
                const auto& client = clients_[key];
                char ip_str[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &client.address.sin_addr, 
                         ip_str, sizeof(ip_str));
                
                LOG_INFO("Client %s:%d disconnected (inactive). "
                        "Packets: %lu, Bytes: %lu",
                        ip_str, ntohs(client.address.sin_port),
                        client.packet_count, client.total_bytes);
                
                clients_.erase(key);
            }
        }
        
        if (!to_remove.empty()) {
            LOG_INFO("Cleaned up %zu inactive clients", to_remove.size());
        }
    }
    
    // 獲取客戶端統(tǒng)計(jì)信息
    std::string GetStats() const {
        std::lock_guard<std::mutex> lock(clients_mutex_);
        
        std::stringstream ss;
        ss << "Active clients: " << clients_.size() << "\n";
        
        for (const auto& pair : clients_) {
            char ip_str[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &pair.second.address.sin_addr, 
                     ip_str, sizeof(ip_str));
            
            ss << ip_str << ":" << ntohs(pair.second.address.sin_port)
               << " - Packets: " << pair.second.packet_count
               << ", Bytes: " << pair.second.total_bytes
               << ", Last activity: " 
               << (time(nullptr) - pair.second.last_activity) 
               << " seconds ago\n";
        }
        
        return ss.str();
    }
    
private:
    std::string GetClientKey(const sockaddr_in& addr) const {
        std::stringstream ss;
        ss << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port);
        return ss.str();
    }
};

二、Main.cc實(shí)現(xiàn)

主程序負(fù)責(zé)初始化服務(wù)器并處理命令行參數(shù)。

#include <iostream>
#include <csignal>
#include <cstdlib>
#include <memory>
#include "UdpServer.hpp"
#include "AdvancedUdpServer.hpp"

// 全局服務(wù)器指針,用于信號(hào)處理
std::unique_ptr<UdpServer> g_server;

// 信號(hào)處理函數(shù)
void SignalHandler(int signal) {
    std::cout << "\nReceived signal " << signal << ", shutting down..." << std::endl;
    if (g_server) {
        g_server->Stop();
    }
}

// 顯示使用幫助
void ShowUsage(const char* program_name) {
    std::cout << "UDP Server v1.0\n\n";
    std::cout << "Usage: " << program_name << " [options]\n\n";
    std::cout << "Options:\n";
    std::cout << "  -p, --port PORT      Server port (default: 8080)\n";
    std::cout << "  -b, --buffer SIZE    Buffer size in bytes (default: 4096)\n";
    std::cout << "  -t, --timeout SEC    Receive timeout in seconds (default: 5)\n";
    std::cout << "  -w, --workers NUM    Number of worker threads (default: 1)\n";
    std::cout << "  -a, --advanced       Use advanced server with thread pool\n";
    std::cout << "  -h, --help           Show this help message\n";
    std::cout << "\nExamples:\n";
    std::cout << "  " << program_name << " -p 9000 -b 8192\n";
    std::cout << "  " << program_name << " --port 8080 --workers 4 --advanced\n";
}

// 解析命令行參數(shù)
struct ServerConfig {
    int port = 8080;
    size_t buffer_size = 4096;
    int timeout_sec = 5;
    int timeout_usec = 0;
    int workers = 1;
    bool advanced = false;
    bool reuse_addr = true;
};

ServerConfig ParseArguments(int argc, char* argv[]) {
    ServerConfig config;
    
    for (int i = 1; i < argc; i++) {
        std::string arg = argv[i];
        
        if (arg == "-p" || arg == "--port") {
            if (i + 1 < argc) {
                config.port = std::atoi(argv[++i]);
                if (config.port <= 0 || config.port > 65535) {
                    std::cerr << "Error: Port must be between 1 and 65535" << std::endl;
                    exit(1);
                }
            }
        } else if (arg == "-b" || arg == "--buffer") {
            if (i + 1 < argc) {
                config.buffer_size = std::atoi(argv[++i]);
                if (config.buffer_size < 1024 || config.buffer_size > 65536) {
                    std::cerr << "Error: Buffer size must be between 1024 and 65536" << std::endl;
                    exit(1);
                }
            }
        } else if (arg == "-t" || arg == "--timeout") {
            if (i + 1 < argc) {
                config.timeout_sec = std::atoi(argv[++i]);
                if (config.timeout_sec < 0) {
                    std::cerr << "Error: Timeout must be non-negative" << std::endl;
                    exit(1);
                }
            }
        } else if (arg == "-w" || arg == "--workers") {
            if (i + 1 < argc) {
                config.workers = std::atoi(argv[++i]);
                if (config.workers < 1 || config.workers > 32) {
                    std::cerr << "Error: Number of workers must be between 1 and 32" << std::endl;
                    exit(1);
                }
            }
        } else if (arg == "-a" || arg == "--advanced") {
            config.advanced = true;
        } else if (arg == "-h" || arg == "--help") {
            ShowUsage(argv[0]);
            exit(0);
        } else if (arg == "--no-reuse") {
            config.reuse_addr = false;
        } else {
            std::cerr << "Error: Unknown option '" << arg << "'" << std::endl;
            ShowUsage(argv[0]);
            exit(1);
        }
    }
    
    return config;
}

int main(int argc, char* argv[]) {
    // 解析命令行參數(shù)
    ServerConfig config = ParseArguments(argc, argv);
    
    // 注冊(cè)信號(hào)處理
    signal(SIGINT, SignalHandler);
    signal(SIGTERM, SignalHandler);
    
    try {
        std::cout << "=== UDP Server Starting ===\n";
        std::cout << "Port: " << config.port << "\n";
        std::cout << "Buffer size: " << config.buffer_size << " bytes\n";
        std::cout << "Timeout: " << config.timeout_sec << " seconds\n";
        std::cout << "Workers: " << config.workers << "\n";
        std::cout << "Mode: " << (config.advanced ? "Advanced" : "Basic") << "\n";
        std::cout << "===========================\n\n";
        
        // 創(chuàng)建服務(wù)器實(shí)例
        if (config.advanced) {
            g_server = std::make_unique<AdvancedUdpServer>(config.port, config.workers);
        } else {
            g_server = std::make_unique<UdpServer>(config.port);
        }
        
        // 配置服務(wù)器
        g_server->SetBufferSize(config.buffer_size);
        g_server->SetTimeout(config.timeout_sec, config.timeout_usec);
        g_server->SetReuseAddr(config.reuse_addr);
        
        // 初始化服務(wù)器
        if (!g_server->Init()) {
            std::cerr << "Failed to initialize server" << std::endl;
            return 1;
        }
        
        std::cout << "Server initialized successfully\n";
        std::cout << "Press Ctrl+C to stop the server\n\n";
        
        // 運(yùn)行服務(wù)器
        g_server->Run();
        
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "Unknown exception occurred" << std::endl;
        return 1;
    }
    
    std::cout << "\nServer stopped gracefully" << std::endl;
    return 0;
}

// 性能測(cè)試函數(shù)
void RunPerformanceTest(int port) {
    std::cout << "\n=== Performance Test ===\n";
    
    // 創(chuàng)建測(cè)試服務(wù)器
    auto test_server = std::make_unique<AdvancedUdpServer>(port, 4);
    test_server->SetBufferSize(65536);
    test_server->SetTimeout(1, 0);
    
    if (!test_server->Init()) {
        std::cerr << "Failed to initialize test server" << std::endl;
        return;
    }
    
    // 在后臺(tái)運(yùn)行服務(wù)器
    std::thread server_thread([&test_server]() {
        test_server->Run();
    });
    
    // 給服務(wù)器時(shí)間啟動(dòng)
    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    // 創(chuàng)建測(cè)試客戶端
    int client_sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (client_sock < 0) {
        std::cerr << "Failed to create test client socket" << std::endl;
        return;
    }
    
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    
    // 測(cè)試參數(shù)
    const int NUM_PACKETS = 10000;
    const int PACKET_SIZE = 1024;
    
    std::vector<char> test_data(PACKET_SIZE, 'X');
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 發(fā)送測(cè)試數(shù)據(jù)包
    for (int i = 0; i < NUM_PACKETS; i++) {
        // 在數(shù)據(jù)中包含序列號(hào)
        memcpy(test_data.data(), &i, sizeof(i));
        
        ssize_t sent = sendto(client_sock, test_data.data(), PACKET_SIZE, 0,
                             (struct sockaddr*)&server_addr, sizeof(server_addr));
        
        if (sent != PACKET_SIZE) {
            std::cerr << "Failed to send packet " << i << std::endl;
            break;
        }
        
        // 每1000個(gè)包打印進(jìn)度
        if ((i + 1) % 1000 == 0) {
            std::cout << "Sent " << (i + 1) << " packets..." << std::endl;
        }
        
        // 小延遲避免擁塞
        usleep(10);
    }
    
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
        end_time - start_time);
    
    close(client_sock);
    
    // 停止服務(wù)器
    test_server->Stop();
    if (server_thread.joinable()) {
        server_thread.join();
    }
    
    // 輸出結(jié)果
    std::cout << "\nPerformance Test Results:\n";
    std::cout << "Packets sent: " << NUM_PACKETS << "\n";
    std::cout << "Packet size: " << PACKET_SIZE << " bytes\n";
    std::cout << "Total data: " 
              << (NUM_PACKETS * PACKET_SIZE / 1024.0 / 1024.0) 
              << " MB\n";
    std::cout << "Total time: " << duration.count() << " ms\n";
    std::cout << "Throughput: " 
              << (NUM_PACKETS * PACKET_SIZE * 8.0 / duration.count() / 1000.0) 
              << " Mbps\n";
    std::cout << "Packets per second: " 
              << (NUM_PACKETS * 1000.0 / duration.count()) 
              << "\n";
}

三、UDP客戶端UdpClient.cc

3.1 基本框架設(shè)計(jì)

UDP客戶端的設(shè)計(jì)需要簡(jiǎn)潔高效,支持多種操作模式。

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <vector>
#include <chrono>
#include <thread>
#include <atomic>
#include <memory>
#include <iomanip>

class UdpClient {
private:
    int sockfd_;                    // 套接字描述符
    struct sockaddr_in server_addr_; // 服務(wù)器地址
    std::string server_ip_;         // 服務(wù)器IP地址
    int server_port_;               // 服務(wù)器端口
    
    // 客戶端狀態(tài)
    std::atomic<bool> is_connected_;
    std::atomic<bool> is_running_;
    
    // 統(tǒng)計(jì)信息
    uint64_t packets_sent_;
    uint64_t packets_received_;
    uint64_t bytes_sent_;
    uint64_t bytes_received_;
    
public:
    // 構(gòu)造函數(shù)
    UdpClient(const std::string& ip = "127.0.0.1", int port = 8080);
    
    // 析構(gòu)函數(shù)
    ~UdpClient();
    
    // 初始化客戶端
    bool Init();
    
    // 連接服務(wù)器
    bool Connect();
    
    // 發(fā)送數(shù)據(jù)
    bool Send(const std::string& data);
    bool Send(const void* data, size_t len);
    
    // 接收數(shù)據(jù)(阻塞)
    bool Receive(std::string& data, int timeout_ms = 5000);
    
    // 發(fā)送并等待響應(yīng)
    bool SendAndReceive(const std::string& send_data, 
                       std::string& recv_data, 
                       int timeout_ms = 5000);
    
    // 運(yùn)行交互模式
    void RunInteractive();
    
    // 運(yùn)行性能測(cè)試模式
    void RunPerformanceTest(int num_packets = 1000, 
                           int packet_size = 1024);
    
    // 獲取統(tǒng)計(jì)信息
    void GetStats(uint64_t& sent_packets, uint64_t& received_packets,
                 uint64_t& sent_bytes, uint64_t& received_bytes) const;
    
    // 重置統(tǒng)計(jì)信息
    void ResetStats();
    
    // 斷開(kāi)連接
    void Disconnect();
    
private:
    // 創(chuàng)建套接字
    bool CreateSocket();
    
    // 設(shè)置套接字選項(xiàng)
    bool SetSocketOptions();
    
    // 打印狀態(tài)
    void PrintStatus() const;
    
    // 顯示幫助信息
    void ShowHelp() const;
};

#endif // UDPCLIENT_H

3.2 創(chuàng)建套接字和連接

#include "UdpClient.h"

UdpClient::UdpClient(const std::string& ip, int port)
    : server_ip_(ip), server_port_(port),
      sockfd_(-1), is_connected_(false), is_running_(false),
      packets_sent_(0), packets_received_(0),
      bytes_sent_(0), bytes_received_(0) {
    
    // 初始化服務(wù)器地址結(jié)構(gòu)
    memset(&server_addr_, 0, sizeof(server_addr_));
    server_addr_.sin_family = AF_INET;
    server_addr_.sin_port = htons(server_port_);
    
    // 轉(zhuǎn)換IP地址
    if (inet_pton(AF_INET, server_ip_.c_str(), &server_addr_.sin_addr) <= 0) {
        std::cerr << "Invalid IP address: " << server_ip_ << std::endl;
    }
}

UdpClient::~UdpClient() {
    Disconnect();
}

bool UdpClient::Init() {
    // 創(chuàng)建套接字
    if (!CreateSocket()) {
        std::cerr << "Failed to create socket" << std::endl;
        return false;
    }
    
    // 設(shè)置套接字選項(xiàng)
    if (!SetSocketOptions()) {
        std::cerr << "Failed to set socket options" << std::endl;
        close(sockfd_);
        return false;
    }
    
    std::cout << "UDP client initialized" << std::endl;
    std::cout << "Server: " << server_ip_ << ":" << server_port_ << std::endl;
    
    return true;
}

bool UdpClient::CreateSocket() {
    // 創(chuàng)建UDP套接字
    sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd_ < 0) {
        std::cerr << "Socket creation failed: " << strerror(errno) << std::endl;
        return false;
    }
    
    std::cout << "Socket created successfully (fd: " << sockfd_ << ")" << std::endl;
    return true;
}

bool UdpClient::SetSocketOptions() {
    int optval = 1;
    
    // 設(shè)置接收超時(shí)
    struct timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    
    if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
        std::cerr << "Failed to set receive timeout: " << strerror(errno) << std::endl;
        return false;
    }
    
    // 啟用廣播(如果需要)
    optval = 1;
    if (setsockopt(sockfd_, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
        std::cerr << "Warning: Failed to enable broadcast: " << strerror(errno) << std::endl;
    }
    
    // 設(shè)置緩沖區(qū)大小
    int buf_size = 1024 * 1024; // 1MB
    if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)) < 0) {
        std::cerr << "Warning: Failed to set receive buffer: " << strerror(errno) << std::endl;
    }
    
    if (setsockopt(sockfd_, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)) < 0) {
        std::cerr << "Warning: Failed to set send buffer: " << strerror(errno) << std::endl;
    }
    
    return true;
}

bool UdpClient::Connect() {
    if (sockfd_ < 0) {
        std::cerr << "Socket not initialized" << std::endl;
        return false;
    }
    
    // UDP是無(wú)連接的,這里只是測(cè)試與服務(wù)器的連通性
    std::string test_msg = "CONNECT_TEST";
    std::string response;
    
    if (SendAndReceive(test_msg, response, 3000)) {
        std::cout << "Successfully connected to server" << std::endl;
        std::cout << "Server response: " << response << std::endl;
        is_connected_ = true;
        return true;
    } else {
        std::cerr << "Failed to connect to server" << std::endl;
        return false;
    }
}

3.3 發(fā)送和接收數(shù)據(jù)

bool UdpClient::Send(const std::string& data) {
    return Send(data.c_str(), data.length());
}

bool UdpClient::Send(const void* data, size_t len) {
    if (sockfd_ < 0) {
        std::cerr << "Socket not initialized" << std::endl;
        return false;
    }
    
    if (len == 0) {
        std::cerr << "Attempting to send empty data" << std::endl;
        return false;
    }
    
    // 檢查數(shù)據(jù)包大小
    if (len > 65507) {
        std::cerr << "Data too large: " << len << " bytes (max: 65507)" << std::endl;
        return false;
    }
    
    // 發(fā)送數(shù)據(jù)
    ssize_t sent = sendto(sockfd_, data, len, 0,
                         (struct sockaddr*)&server_addr_, 
                         sizeof(server_addr_));
    
    if (sent < 0) {
        std::cerr << "Send failed: " << strerror(errno) << std::endl;
        return false;
    }
    
    if (static_cast<size_t>(sent) != len) {
        std::cerr << "Partial send: " << sent << " of " << len << " bytes" << std::endl;
    }
    
    // 更新統(tǒng)計(jì)信息
    packets_sent_++;
    bytes_sent_ += sent;
    
    std::cout << "Sent " << sent << " bytes to " 
              << server_ip_ << ":" << server_port_ << std::endl;
    
    return true;
}

bool UdpClient::Receive(std::string& data, int timeout_ms) {
    if (sockfd_ < 0) {
        std::cerr << "Socket not initialized" << std::endl;
        return false;
    }
    
    // 設(shè)置接收超時(shí)
    if (timeout_ms > 0) {
        struct timeval tv;
        tv.tv_sec = timeout_ms / 1000;
        tv.tv_usec = (timeout_ms % 1000) * 1000;
        setsockopt(sockfd_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    }
    
    // 接收緩沖區(qū)
    char buffer[65536];
    struct sockaddr_in from_addr;
    socklen_t addr_len = sizeof(from_addr);
    
    // 接收數(shù)據(jù)
    ssize_t recv_len = recvfrom(sockfd_, buffer, sizeof(buffer) - 1, 0,
                               (struct sockaddr*)&from_addr, &addr_len);
    
    if (recv_len < 0) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            std::cout << "Receive timeout" << std::endl;
        } else {
            std::cerr << "Receive failed: " << strerror(errno) << std::endl;
        }
        return false;
    }
    
    // 確保字符串以null結(jié)尾
    buffer[recv_len] = '\0';
    data.assign(buffer, recv_len);
    
    // 獲取發(fā)送者信息
    char from_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &from_addr.sin_addr, from_ip, sizeof(from_ip));
    uint16_t from_port = ntohs(from_addr.sin_port);
    
    // 更新統(tǒng)計(jì)信息
    packets_received_++;
    bytes_received_ += recv_len;
    
    std::cout << "Received " << recv_len << " bytes from " 
              << from_ip << ":" << from_port << std::endl;
    
    return true;
}

bool UdpClient::SendAndReceive(const std::string& send_data, 
                              std::string& recv_data, 
                              int timeout_ms) {
    // 發(fā)送數(shù)據(jù)
    if (!Send(send_data)) {
        return false;
    }
    
    // 接收響應(yīng)
    if (!Receive(recv_data, timeout_ms)) {
        return false;
    }
    
    return true;
}

3.4 交互模式和性能測(cè)試

void UdpClient::RunInteractive() {
    if (!is_connected_) {
        if (!Connect()) {
            std::cerr << "Cannot start interactive mode: not connected" << std::endl;
            return;
        }
    }
    
    is_running_ = true;
    std::cout << "\n=== UDP Client Interactive Mode ===\n";
    std::cout << "Type 'help' for commands, 'quit' to exit\n\n";
    
    std::string input;
    while (is_running_) {
        std::cout << "udp> ";
        std::getline(std::cin, input);
        
        if (input.empty()) {
            continue;
        }
        
        // 處理命令
        if (input == "quit" || input == "exit") {
            std::cout << "Exiting..." << std::endl;
            break;
        } else if (input == "help") {
            ShowHelp();
        } else if (input == "status") {
            PrintStatus();
        } else if (input == "stats") {
            std::cout << "\n=== Statistics ===\n";
            std::cout << "Packets sent: " << packets_sent_ << "\n";
            std::cout << "Packets received: " << packets_received_ << "\n";
            std::cout << "Bytes sent: " << bytes_sent_ << "\n";
            std::cout << "Bytes received: " << bytes_received_ << "\n";
            
            if (packets_sent_ > 0) {
                std::cout << "Average sent size: " 
                          << (bytes_sent_ / packets_sent_) << " bytes\n";
            }
            if (packets_received_ > 0) {
                std::cout << "Average received size: " 
                          << (bytes_received_ / packets_received_) << " bytes\n";
            }
        } else if (input == "reset") {
            ResetStats();
            std::cout << "Statistics reset" << std::endl;
        } else if (input == "ping") {
            std::string response;
            if (SendAndReceive("PING", response)) {
                std::cout << "Server response: " << response << std::endl;
            }
        } else if (input == "time") {
            std::string response;
            if (SendAndReceive("TIME", response)) {
                std::cout << "Server time: " << response;
            }
        } else if (input.compare(0, 4, "echo") == 0) {
            if (input.length() > 5) {
                std::string echo_data = input.substr(5);
                std::string response;
                if (SendAndReceive("ECHO " + echo_data, response)) {
                    std::cout << "Echo: " << response << std::endl;
                }
            } else {
                std::cout << "Usage: echo <message>" << std::endl;
            }
        } else if (input.compare(0, 4, "file") == 0) {
            // 模擬文件傳輸
            std::string filename = input.length() > 5 ? input.substr(5) : "test.txt";
            std::cout << "Simulating file transfer: " << filename << std::endl;
            
            // 創(chuàng)建模擬文件內(nèi)容
            std::string file_content;
            for (int i = 0; i < 100; i++) {
                file_content += "Line " + std::to_string(i + 1) + ": This is test data\n";
            }
            
            // 分塊發(fā)送
            const size_t CHUNK_SIZE = 1024;
            size_t total_sent = 0;
            int chunk_num = 1;
            
            for (size_t i = 0; i < file_content.length(); i += CHUNK_SIZE) {
                size_t chunk_len = std::min(CHUNK_SIZE, file_content.length() - i);
                std::string chunk = file_content.substr(i, chunk_len);
                
                // 添加塊頭信息
                std::string chunk_with_header = "FILE_CHUNK " + 
                                               std::to_string(chunk_num) + " " +
                                               chunk;
                
                if (Send(chunk_with_header)) {
                    total_sent += chunk_len;
                    std::cout << "Sent chunk " << chunk_num 
                              << " (" << chunk_len << " bytes)" << std::endl;
                    chunk_num++;
                    
                    // 小延遲
                    usleep(10000); // 10ms
                } else {
                    std::cerr << "Failed to send chunk " << chunk_num << std::endl;
                    break;
                }
            }
            
            std::cout << "File transfer complete: " << total_sent << " bytes sent" << std::endl;
            
        } else if (input == "perftest") {
            RunPerformanceTest();
        } else {
            // 默認(rèn):發(fā)送原始消息
            std::string response;
            if (SendAndReceive(input, response)) {
                std::cout << "Response: " << response << std::endl;
            }
        }
    }
}

void UdpClient::RunPerformanceTest(int num_packets, int packet_size) {
    std::cout << "\n=== Performance Test ===\n";
    std::cout << "Packets: " << num_packets << "\n";
    std::cout << "Packet size: " << packet_size << " bytes\n";
    std::cout << "Total data: " 
              << (num_packets * packet_size / 1024.0 / 1024.0) 
              << " MB\n\n";
    
    // 準(zhǔn)備測(cè)試數(shù)據(jù)
    std::vector<char> test_data(packet_size, 'X');
    
    // 記錄開(kāi)始時(shí)間
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 發(fā)送測(cè)試數(shù)據(jù)包
    int successful_sends = 0;
    for (int i = 0; i < num_packets; i++) {
        // 在數(shù)據(jù)中包含序列號(hào)和時(shí)間戳
        uint64_t seq = i;
        auto timestamp = std::chrono::high_resolution_clock::now();
        uint64_t timestamp_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
            timestamp.time_since_epoch()).count();
        
        // 將序列號(hào)和時(shí)間戳復(fù)制到數(shù)據(jù)開(kāi)始處
        memcpy(test_data.data(), &seq, sizeof(seq));
        memcpy(test_data.data() + sizeof(seq), &timestamp_ns, sizeof(timestamp_ns));
        
        if (Send(test_data.data(), packet_size)) {
            successful_sends++;
        }
        
        // 每100個(gè)包打印進(jìn)度
        if ((i + 1) % 100 == 0) {
            std::cout << "Sent " << (i + 1) << " packets..." << std::endl;
        }
        
        // 控制發(fā)送速率(1000 packets/second)
        usleep(1000);
    }
    
    // 記錄結(jié)束時(shí)間
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
        end_time - start_time);
    
    // 接收響應(yīng)(可選)
    std::cout << "\nWaiting for responses..." << std::endl;
    
    int responses_received = 0;
    auto receive_start = std::chrono::high_resolution_clock::now();
    
    // 設(shè)置短超時(shí)接收剩余響應(yīng)
    struct timeval tv;
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    setsockopt(sockfd_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    
    char buffer[65536];
    while (true) {
        ssize_t recv_len = recvfrom(sockfd_, buffer, sizeof(buffer) - 1, 0, NULL, NULL);
        if (recv_len > 0) {
            responses_received++;
            
            // 解析響應(yīng)中的序列號(hào)
            if (recv_len >= sizeof(uint64_t)) {
                uint64_t seq;
                memcpy(&seq, buffer, sizeof(seq));
                // 可以在這里計(jì)算往返時(shí)間等
            }
        } else {
            break; // 超時(shí)
        }
    }
    
    auto receive_end = std::chrono::high_resolution_clock::now();
    auto receive_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
        receive_end - receive_start);
    
    // 輸出結(jié)果
    std::cout << "\n=== Test Results ===\n";
    std::cout << "Packets sent: " << successful_sends << "/" << num_packets << "\n";
    std::cout << "Responses received: " << responses_received << "\n";
    std::cout << "Send duration: " << duration.count() << " ms\n";
    std::cout << "Receive duration: " << receive_duration.count() << " ms\n";
    
    if (duration.count() > 0) {
        double send_rate = (successful_sends * 1000.0) / duration.count();
        double throughput = (successful_sends * packet_size * 8.0) / 
                           (duration.count() * 1000.0); // Mbps
        
        std::cout << "Send rate: " << send_rate << " packets/second\n";
        std::cout << "Throughput: " << throughput << " Mbps\n";
    }
    
    if (responses_received > 0) {
        double response_rate = (responses_received * 1000.0) / receive_duration.count();
        std::cout << "Response rate: " << response_rate << " packets/second\n";
    }
    
    double loss_rate = 0;
    if (successful_sends > 0) {
        loss_rate = (1.0 - (responses_received / (double)successful_sends)) * 100.0;
        std::cout << "Packet loss rate: " << std::fixed << std::setprecision(2) 
                  << loss_rate << "%\n";
    }
}

void UdpClient::ShowHelp() const {
    std::cout << "\nAvailable commands:\n";
    std::cout << "  help              Show this help message\n";
    std::cout << "  quit, exit        Exit the client\n";
    std::cout << "  status            Show connection status\n";
    std::cout << "  stats             Show statistics\n";
    std::cout << "  reset             Reset statistics\n";
    std::cout << "  ping              Send ping to server\n";
    std::cout << "  time              Get server time\n";
    std::cout << "  echo <message>    Echo message to server\n";
    std::cout << "  file [name]       Simulate file transfer\n";
    std::cout << "  perftest          Run performance test\n";
    std::cout << "  <any text>        Send custom message\n";
}

void UdpClient::PrintStatus() const {
    std::cout << "\n=== Client Status ===\n";
    std::cout << "Server: " << server_ip_ << ":" << server_port_ << "\n";
    std::cout << "Socket: " << (sockfd_ >= 0 ? "OK" : "Not initialized") << "\n";
    std::cout << "Connected: " << (is_connected_ ? "Yes" : "No") << "\n";
    std::cout << "Running: " << (is_running_ ? "Yes" : "No") << "\n";
}

void UdpClient::GetStats(uint64_t& sent_packets, uint64_t& received_packets,
                        uint64_t& sent_bytes, uint64_t& received_bytes) const {
    sent_packets = packets_sent_;
    received_packets = packets_received_;
    sent_bytes = bytes_sent_;
    received_bytes = bytes_received_;
}

void UdpClient::ResetStats() {
    packets_sent_ = 0;
    packets_received_ = 0;
    bytes_sent_ = 0;
    bytes_received_ = 0;
}

void UdpClient::Disconnect() {
    if (sockfd_ >= 0) {
        // 發(fā)送斷開(kāi)連接消息
        std::string disconnect_msg = "DISCONNECT";
        Send(disconnect_msg);
        
        // 關(guān)閉套接字
        close(sockfd_);
        sockfd_ = -1;
        
        std::cout << "Disconnected from server" << std::endl;
    }
    
    is_connected_ = false;
    is_running_ = false;
}

// 客戶端主程序
int main(int argc, char* argv[]) {
    std::string server_ip = "127.0.0.1";
    int server_port = 8080;
    
    // 解析命令行參數(shù)
    for (int i = 1; i < argc; i++) {
        std::string arg = argv[i];
        if (arg == "-s" || arg == "--server") {
            if (i + 1 < argc) {
                server_ip = argv[++i];
            }
        } else if (arg == "-p" || arg == "--port") {
            if (i + 1 < argc) {
                server_port = std::atoi(argv[++i]);
            }
        } else if (arg == "-h" || arg == "--help") {
            std::cout << "UDP Client Usage:\n";
            std::cout << "  -s, --server IP    Server IP address (default: 127.0.0.1)\n";
            std::cout << "  -p, --port PORT    Server port (default: 8080)\n";
            std::cout << "  -t, --test         Run performance test\n";
            std::cout << "  -i, --interactive  Run in interactive mode\n";
            std::cout << "  -h, --help         Show this help\n";
            return 0;
        } else if (arg == "-t" || arg == "--test") {
            // 性能測(cè)試模式
            UdpClient client(server_ip, server_port);
            if (client.Init() && client.Connect()) {
                client.RunPerformanceTest();
            }
            return 0;
        } else if (arg == "-i" || arg == "--interactive") {
            // 交互模式(默認(rèn))
        }
    }
    
    std::cout << "=== UDP Client ===\n";
    std::cout << "Connecting to " << server_ip << ":" << server_port << "\n\n";
    
    UdpClient client(server_ip, server_port);
    
    if (!client.Init()) {
        std::cerr << "Failed to initialize client" << std::endl;
        return 1;
    }
    
    if (!client.Connect()) {
        std::cerr << "Failed to connect to server" << std::endl;
        return 1;
    }
    
    // 運(yùn)行交互模式
    client.RunInteractive();
    
    std::cout << "\nClient terminated" << std::endl;
    return 0;
}

四、測(cè)試

4.1 單元測(cè)試

// TestUdpServer.cpp
#include <gtest/gtest.h>
#include <thread>
#include <chrono>
#include "UdpServer.hpp"
#include "UdpClient.h"

class UdpServerTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 啟動(dòng)測(cè)試服務(wù)器
        test_port_ = 9999;
        server_ = std::make_unique<UdpServer>(test_port_);
        ASSERT_TRUE(server_->Init());
        
        // 在后臺(tái)線程運(yùn)行服務(wù)器
        server_thread_ = std::thread([this]() {
            server_->Run();
        });
        
        // 等待服務(wù)器啟動(dòng)
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    
    void TearDown() override {
        if (server_) {
            server_->Stop();
        }
        if (server_thread_.joinable()) {
            server_thread_.join();
        }
    }
    
    int test_port_;
    std::unique_ptr<UdpServer> server_;
    std::thread server_thread_;
};

TEST_F(UdpServerTest, BasicEcho) {
    UdpClient client("127.0.0.1", test_port_);
    ASSERT_TRUE(client.Init());
    
    std::string send_data = "Hello, Server!";
    std::string recv_data;
    
    EXPECT_TRUE(client.SendAndReceive(send_data, recv_data));
    EXPECT_NE(recv_data.find("Server received"), std::string::npos);
    EXPECT_NE(recv_data.find(send_data), std::string::npos);
}

TEST_F(UdpServerTest, MultipleClients) {
    const int NUM_CLIENTS = 5;
    std::vector<std::unique_ptr<UdpClient>> clients;
    std::vector<std::thread> client_threads;
    
    for (int i = 0; i < NUM_CLIENTS; i++) {
        auto client = std::make_unique<UdpClient>("127.0.0.1", test_port_);
        ASSERT_TRUE(client->Init());
        clients.push_back(std::move(client));
    }
    
    // 并發(fā)發(fā)送消息
    for (int i = 0; i < NUM_CLIENTS; i++) {
        client_threads.emplace_back([&clients, i]() {
            std::string send_data = "Message from client " + std::to_string(i);
            std::string recv_data;
            EXPECT_TRUE(clients[i]->SendAndReceive(send_data, recv_data, 3000));
        });
    }
    
    // 等待所有線程完成
    for (auto& thread : client_threads) {
        thread.join();
    }
}

TEST_F(UdpServerTest, LargeData) {
    UdpClient client("127.0.0.1", test_port_);
    ASSERT_TRUE(client.Init());
    
    // 發(fā)送較大數(shù)據(jù)(小于64KB)
    std::string large_data(50000, 'X');  // 50KB
    std::string recv_data;
    
    EXPECT_TRUE(client.SendAndReceive(large_data, recv_data, 5000));
    EXPECT_GT(recv_data.size(), large_data.size());
}

TEST_F(UdpServerTest, Performance) {
    UdpClient client("127.0.0.1", test_port_);
    ASSERT_TRUE(client.Init());
    
    const int NUM_PACKETS = 100;
    const int PACKET_SIZE = 1400;  // 避免分片
    
    auto start_time = std::chrono::high_resolution_clock::now();
    
    int success_count = 0;
    for (int i = 0; i < NUM_PACKETS; i++) {
        std::string data(PACKET_SIZE, 'A' + (i % 26));
        std::string response;
        if (client.SendAndReceive(data, response, 1000)) {
            success_count++;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
        end_time - start_time);
    
    std::cout << "\nPerformance Test Results:\n";
    std::cout << "Successful exchanges: " << success_count << "/" << NUM_PACKETS << "\n";
    std::cout << "Total time: " << duration.count() << " ms\n";
    std::cout << "Average RTT: " << (duration.count() / (double)success_count) << " ms\n";
    
    EXPECT_GT(success_count, NUM_PACKETS * 0.9);  // 90%成功率
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

4.2 集成測(cè)試

// IntegrationTest.cpp
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include "AdvancedUdpServer.hpp"
#include "UdpClient.h"

class IntegrationTest {
private:
    std::unique_ptr<AdvancedUdpServer> server_;
    std::thread server_thread_;
    int server_port_;
    
public:
    IntegrationTest(int port = 8888, int workers = 4) 
        : server_port_(port) {
        // 啟動(dòng)高性能服務(wù)器
        server_ = std::make_unique<AdvancedUdpServer>(port, workers);
        server_->SetBufferSize(65536);
        server_->SetTimeout(1, 0);
        
        if (!server_->Init()) {
            throw std::runtime_error("Failed to initialize server");
        }
        
        // 在后臺(tái)運(yùn)行服務(wù)器
        server_thread_ = std::thread([this]() {
            server_->Run();
        });
        
        // 等待服務(wù)器啟動(dòng)
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        std::cout << "Test server started on port " << port << std::endl;
    }
    
    ~IntegrationTest() {
        if (server_) {
            server_->Stop();
        }
        if (server_thread_.joinable()) {
            server_thread_.join();
        }
        std::cout << "Test server stopped" << std::endl;
    }
    
    void RunLoadTest(int num_clients, int messages_per_client) {
        std::cout << "\n=== Load Test ===\n";
        std::cout << "Clients: " << num_clients << "\n";
        std::cout << "Messages per client: " << messages_per_client << "\n";
        
        std::vector<std::thread> client_threads;
        std::atomic<int> total_success{0};
        std::atomic<int> total_failures{0};
        
        auto start_time = std::chrono::high_resolution_clock::now();
        
        // 創(chuàng)建客戶端線程
        for (int client_id = 0; client_id < num_clients; client_id++) {
            client_threads.emplace_back([this, client_id, messages_per_client,
                                       &total_success, &total_failures]() {
                UdpClient client("127.0.0.1", server_port_);
                if (!client.Init()) {
                    total_failures += messages_per_client;
                    return;
                }
                
                int local_success = 0;
                int local_failures = 0;
                
                for (int msg_num = 0; msg_num < messages_per_client; msg_num++) {
                    std::string message = "Client" + std::to_string(client_id) + 
                                         "_Msg" + std::to_string(msg_num);
                    std::string response;
                    
                    if (client.SendAndReceive(message, response, 1000)) {
                        local_success++;
                        
                        // 驗(yàn)證響應(yīng)包含原始消息
                        if (response.find(message) == std::string::npos) {
                            std::cerr << "Warning: Invalid response from server" << std::endl;
                        }
                    } else {
                        local_failures++;
                    }
                    
                    // 小延遲避免擁塞
                    std::this_thread::sleep_for(std::chrono::milliseconds(10));
                }
                
                total_success += local_success;
                total_failures += local_failures;
                
                std::cout << "Client " << client_id << ": " 
                          << local_success << "/" << messages_per_client 
                          << " successful" << std::endl;
            });
        }
        
        // 等待所有客戶端完成
        for (auto& thread : client_threads) {
            thread.join();
        }
        
        auto end_time = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            end_time - start_time);
        
        // 輸出結(jié)果
        std::cout << "\n=== Load Test Results ===\n";
        std::cout << "Total messages: " << (num_clients * messages_per_client) << "\n";
        std::cout << "Successful: " << total_success << "\n";
        std::cout << "Failed: " << total_failures << "\n";
        std::cout << "Success rate: " 
                  << (total_success * 100.0 / (num_clients * messages_per_client)) 
                  << "%\n";
        std::cout << "Total time: " << duration.count() << " ms\n";
        std::cout << "Throughput: " 
                  << (total_success * 1000.0 / duration.count()) 
                  << " messages/second\n";
        
        // 驗(yàn)證至少95%成功率
        double success_rate = total_success * 100.0 / (num_clients * messages_per_client);
        if (success_rate >= 95.0) {
            std::cout << "\n? Load test PASSED" << std::endl;
        } else {
            std::cout << "\n? Load test FAILED (success rate below 95%)" << std::endl;
        }
    }
    
    void RunStressTest() {
        std::cout << "\n=== Stress Test ===\n";
        
        const int NUM_CLIENTS = 10;
        const int MESSAGES_PER_CLIENT = 1000;
        const int MESSAGE_SIZE = 1000;  // 1KB
        
        std::vector<std::thread> client_threads;
        std::atomic<uint64_t> total_bytes_sent{0};
        std::atomic<uint64_t> total_bytes_received{0};
        
        auto start_time = std::chrono::high_resolution_clock::now();
        
        for (int i = 0; i < NUM_CLIENTS; i++) {
            client_threads.emplace_back([this, i, &total_bytes_sent, &total_bytes_received]() {
                UdpClient client("127.0.0.1", server_port_);
                if (!client.Init()) {
                    return;
                }
                
                // 準(zhǔn)備大消息
                std::string large_message(MESSAGE_SIZE, 'A' + (i % 26));
                
                uint64_t client_bytes_sent = 0;
                uint64_t client_bytes_received = 0;
                
                for (int j = 0; j < MESSAGES_PER_CLIENT; j++) {
                    // 修改消息內(nèi)容
                    large_message[0] = '0' + (j % 10);
                    
                    std::string response;
                    if (client.SendAndReceive(large_message, response, 500)) {
                        client_bytes_sent += large_message.size();
                        client_bytes_received += response.size();
                    }
                    
                    // 更短的延遲以增加壓力
                    if (j % 100 == 0) {
                        std::this_thread::sleep_for(std::chrono::microseconds(100));
                    }
                }
                
                total_bytes_sent += client_bytes_sent;
                total_bytes_received += client_bytes_received;
                
                std::cout << "Stress client " << i << " completed" << std::endl;
            });
        }
        
        for (auto& thread : client_threads) {
            thread.join();
        }
        
        auto end_time = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            end_time - start_time);
        
        std::cout << "\n=== Stress Test Results ===\n";
        std::cout << "Total data sent: " 
                  << (total_bytes_sent / 1024.0 / 1024.0) << " MB\n";
        std::cout << "Total data received: " 
                  << (total_bytes_received / 1024.0 / 1024.0) << " MB\n";
        std::cout << "Total time: " << duration.count() << " ms\n";
        
        if (duration.count() > 0) {
            double send_throughput = (total_bytes_sent * 8.0) / 
                                    (duration.count() * 1000.0);  // Mbps
            double receive_throughput = (total_bytes_received * 8.0) / 
                                       (duration.count() * 1000.0);  // Mbps
            
            std::cout << "Send throughput: " << send_throughput << " Mbps\n";
            std::cout << "Receive throughput: " << receive_throughput << " Mbps\n";
            std::cout << "Total throughput: " << (send_throughput + receive_throughput) 
                      << " Mbps\n";
        }
        
        if (total_bytes_sent > 0) {
            std::cout << "\n? Stress test completed successfully" << std::endl;
        }
    }
};

int main() {
    try {
        std::cout << "=== UDP System Integration Test ===\n\n";
        
        IntegrationTest test(8888, 4);
        
        // 運(yùn)行負(fù)載測(cè)試
        test.RunLoadTest(5, 100);
        
        // 運(yùn)行壓力測(cè)試
        test.RunStressTest();
        
        std::cout << "\n=== All tests completed ===\n";
        
    } catch (const std::exception& e) {
        std::cerr << "Test failed: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

4.3 網(wǎng)絡(luò)測(cè)試工具

// NetworkTestTool.cpp
#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
#include <cmath>
#include "UdpClient.h"

class NetworkTestTool {
private:
    std::string server_ip_;
    int server_port_;
    
public:
    NetworkTestTool(const std::string& ip, int port) 
        : server_ip_(ip), server_port_(port) {}
    
    void RunLatencyTest(int num_packets = 100) {
        std::cout << "\n=== Latency Test ===\n";
        std::cout << "Server: " << server_ip_ << ":" << server_port_ << "\n";
        std::cout << "Packets: " << num_packets << "\n\n";
        
        UdpClient client(server_ip_, server_port_);
        if (!client.Init()) {
            std::cerr << "Failed to initialize client" << std::endl;
            return;
        }
        
        std::vector<double> latencies;
        int successful_packets = 0;
        
        for (int i = 0; i < num_packets; i++) {
            // 準(zhǔn)備包含時(shí)間戳的消息
            auto send_time = std::chrono::high_resolution_clock::now();
            uint64_t send_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
                send_time.time_since_epoch()).count();
            
            std::string message = "PING_" + std::to_string(i) + "_" + 
                                 std::to_string(send_ns);
            
            std::string response;
            if (client.SendAndReceive(message, response, 1000)) {
                auto recv_time = std::chrono::high_resolution_clock::now();
                uint64_t recv_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
                    recv_time.time_since_epoch()).count();
                
                // 計(jì)算往返時(shí)間
                double rtt_ns = static_cast<double>(recv_ns - send_ns);
                double rtt_ms = rtt_ns / 1000000.0;
                
                latencies.push_back(rtt_ms);
                successful_packets++;
                
                if ((i + 1) % 10 == 0) {
                    std::cout << "Sent " << (i + 1) << " packets..." << std::endl;
                }
            } else {
                std::cout << "Packet " << i << " lost" << std::endl;
            }
            
            // 等待以避免擁塞
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        
        // 計(jì)算統(tǒng)計(jì)信息
        if (!latencies.empty()) {
            double sum = 0;
            double min_latency = latencies[0];
            double max_latency = latencies[0];
            
            for (double latency : latencies) {
                sum += latency;
                min_latency = std::min(min_latency, latency);
                max_latency = std::max(max_latency, latency);
            }
            
            double average = sum / latencies.size();
            
            // 計(jì)算標(biāo)準(zhǔn)差
            double variance = 0;
            for (double latency : latencies) {
                variance += (latency - average) * (latency - average);
            }
            variance /= latencies.size();
            double stddev = std::sqrt(variance);
            
            // 計(jì)算百分位數(shù)
            std::sort(latencies.begin(), latencies.end());
            double p50 = latencies[latencies.size() * 0.5];
            double p90 = latencies[latencies.size() * 0.9];
            double p95 = latencies[latencies.size() * 0.95];
            double p99 = latencies[latencies.size() * 0.99];
            
            // 輸出結(jié)果
            std::cout << "\n=== Latency Test Results ===\n";
            std::cout << "Packets sent: " << num_packets << "\n";
            std::cout << "Packets received: " << successful_packets << "\n";
            std::cout << "Packet loss: " 
                      << std::fixed << std::setprecision(2)
                      << ((num_packets - successful_packets) * 100.0 / num_packets) 
                      << "%\n";
            std::cout << "\nLatency statistics (ms):\n";
            std::cout << "  Minimum: " << std::fixed << std::setprecision(3) 
                      << min_latency << "\n";
            std::cout << "  Maximum: " << max_latency << "\n";
            std::cout << "  Average: " << average << "\n";
            std::cout << "  Std Dev: " << stddev << "\n";
            std::cout << "  50th percentile: " << p50 << "\n";
            std::cout << "  90th percentile: " << p90 << "\n";
            std::cout << "  95th percentile: " << p95 << "\n";
            std::cout << "  99th percentile: " << p99 << "\n";
            
            // 顯示直方圖
            DisplayHistogram(latencies);
        }
    }
    
    void DisplayHistogram(const std::vector<double>& data) {
        if (data.empty()) return;
        
        double min_val = *std::min_element(data.begin(), data.end());
        double max_val = *std::max_element(data.begin(), data.end());
        
        const int NUM_BINS = 10;
        double bin_width = (max_val - min_val) / NUM_BINS;
        
        std::vector<int> bins(NUM_BINS, 0);
        
        for (double value : data) {
            int bin_index = static_cast<int>((value - min_val) / bin_width);
            if (bin_index == NUM_BINS) bin_index--;  // 處理邊界情況
            bins[bin_index]++;
        }
        
        std::cout << "\nLatency distribution:\n";
        for (int i = 0; i < NUM_BINS; i++) {
            double bin_start = min_val + i * bin_width;
            double bin_end = bin_start + bin_width;
            
            std::cout << std::fixed << std::setprecision(1)
                      << "  " << std::setw(6) << bin_start 
                      << " - " << std::setw(6) << bin_end << " ms: "
                      << std::string(bins[i] * 50 / data.size(), '#')
                      << " (" << bins[i] << ")\n";
        }
    }
    
    void RunBandwidthTest(int duration_sec = 10, int packet_size = 1400) {
        std::cout << "\n=== Bandwidth Test ===\n";
        std::cout << "Duration: " << duration_sec << " seconds\n";
        std::cout << "Packet size: " << packet_size << " bytes\n\n";
        
        UdpClient client(server_ip_, server_port_);
        if (!client.Init()) {
            std::cerr << "Failed to initialize client" << std::endl;
            return;
        }
        
        std::vector<char> packet_data(packet_size, 'B');
        auto start_time = std::chrono::steady_clock::now();
        auto end_time = start_time + std::chrono::seconds(duration_sec);
        
        uint64_t total_packets = 0;
        uint64_t total_bytes = 0;
        uint64_t successful_responses = 0;
        
        std::cout << "Testing bandwidth...\n";
        
        while (std::chrono::steady_clock::now() < end_time) {
            // 發(fā)送數(shù)據(jù)包
            if (client.Send(packet_data.data(), packet_size)) {
                total_packets++;
                total_bytes += packet_size;
            }
            
            // 嘗試接收響應(yīng)(非阻塞)
            std::string response;
            if (client.Receive(response, 10)) {  // 10ms超時(shí)
                successful_responses++;
            }
            
            // 控制發(fā)送速率(約1000 packets/second)
            std::this_thread::sleep_for(std::chrono::microseconds(900));
        }
        
        auto actual_end = std::chrono::steady_clock::now();
        auto actual_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            actual_end - start_time);
        
        // 輸出結(jié)果
        std::cout << "\n=== Bandwidth Test Results ===\n";
        std::cout << "Actual duration: " << actual_duration.count() << " ms\n";
        std::cout << "Packets sent: " << total_packets << "\n";
        std::cout << "Total data sent: " 
                  << (total_bytes / 1024.0 / 1024.0) << " MB\n";
        std::cout << "Responses received: " << successful_responses << "\n";
        
        if (actual_duration.count() > 0) {
            double packets_per_sec = total_packets * 1000.0 / actual_duration.count();
            double bandwidth_mbps = (total_bytes * 8.0) / 
                                   (actual_duration.count() * 1000.0);
            
            std::cout << "Send rate: " << packets_per_sec << " packets/second\n";
            std::cout << "Bandwidth: " << bandwidth_mbps << " Mbps\n";
            std::cout << "Response rate: " 
                      << (successful_responses * 1000.0 / actual_duration.count())
                      << " packets/second\n";
        }
        
        double loss_rate = 0;
        if (total_packets > 0) {
            loss_rate = (1.0 - (successful_responses / (double)total_packets)) * 100.0;
            std::cout << "Estimated loss rate: " 
                      << std::fixed << std::setprecision(2) << loss_rate << "%\n";
        }
    }
};

int main(int argc, char* argv[]) {
    std::string server_ip = "127.0.0.1";
    int server_port = 8080;
    std::string test_type = "latency";
    
    // 解析命令行參數(shù)
    for (int i = 1; i < argc; i++) {
        std::string arg = argv[i];
        if (arg == "-s" || arg == "--server") {
            if (i + 1 < argc) server_ip = argv[++i];
        } else if (arg == "-p" || arg == "--port") {
            if (i + 1 < argc) server_port = std::atoi(argv[++i]);
        } else if (arg == "-t" || arg == "--test") {
            if (i + 1 < argc) test_type = argv[++i];
        } else if (arg == "-h" || arg == "--help") {
            std::cout << "Network Test Tool\n\n";
            std::cout << "Usage: " << argv[0] << " [options]\n\n";
            std::cout << "Options:\n";
            std::cout << "  -s, --server IP    Server IP address\n";
            std::cout << "  -p, --port PORT    Server port\n";
            std::cout << "  -t, --test TYPE    Test type (latency|bandwidth)\n";
            std::cout << "  -h, --help         Show this help\n";
            return 0;
        }
    }
    
    NetworkTestTool tester(server_ip, server_port);
    
    if (test_type == "latency") {
        tester.RunLatencyTest();
    } else if (test_type == "bandwidth") {
        tester.RunBandwidthTest();
    } else {
        std::cerr << "Unknown test type: " << test_type << std::endl;
        std::cerr << "Available types: latency, bandwidth" << std::endl;
        return 1;
    }
    
    return 0;
}

五、源代碼

5.1 Log.hpp - 日志系統(tǒng)

#ifndef LOG_HPP
#define LOG_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
#include <ctime>
#include <mutex>
#include <memory>

// 日志級(jí)別
enum class LogLevel {
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FATAL
};

class Logger {
private:
    static std::shared_ptr<Logger> instance_;
    std::ofstream log_file_;
    LogLevel min_level_;
    std::mutex log_mutex_;
    bool console_output_;
    
    // 私有構(gòu)造函數(shù)
    Logger() : min_level_(LogLevel::INFO), console_output_(true) {}
    
public:
    // 刪除拷貝構(gòu)造函數(shù)和賦值運(yùn)算符
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
    
    // 獲取單例實(shí)例
    static Logger& Instance() {
        static std::shared_ptr<Logger> instance(new Logger());
        return *instance;
    }
    
    // 初始化日志系統(tǒng)
    bool Init(const std::string& filename = "", 
              LogLevel min_level = LogLevel::INFO,
              bool console = true) {
        std::lock_guard<std::mutex> lock(log_mutex_);
        
        min_level_ = min_level;
        console_output_ = console;
        
        if (!filename.empty()) {
            log_file_.open(filename, std::ios::app);
            if (!log_file_.is_open()) {
                std::cerr << "Failed to open log file: " << filename << std::endl;
                return false;
            }
        }
        
        return true;
    }
    
    // 設(shè)置日志級(jí)別
    void SetLevel(LogLevel level) {
        std::lock_guard<std::mutex> lock(log_mutex_);
        min_level_ = level;
    }
    
    // 啟用/禁用控制臺(tái)輸出
    void EnableConsole(bool enable) {
        std::lock_guard<std::mutex> lock(log_mutex_);
        console_output_ = enable;
    }
    
    // 記錄日志
    void Log(LogLevel level, const std::string& message, 
            const char* file = nullptr, int line = 0) {
        if (level < min_level_) {
            return;
        }
        
        std::lock_guard<std::mutex> lock(log_mutex_);
        
        // 獲取當(dāng)前時(shí)間
        auto now = std::chrono::system_clock::now();
        auto now_time = std::chrono::system_clock::to_time_t(now);
        auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now.time_since_epoch()) % 1000;
        
        // 格式化時(shí)間
        std::tm* tm_info = std::localtime(&now_time);
        char time_buffer[80];
        std::strftime(time_buffer, sizeof(time_buffer), 
                     "%Y-%m-%d %H:%M:%S", tm_info);
        
        // 日志級(jí)別字符串
        const char* level_str = "";
        switch (level) {
            case LogLevel::DEBUG: level_str = "DEBUG"; break;
            case LogLevel::INFO:  level_str = "INFO";  break;
            case LogLevel::WARN:  level_str = "WARN";  break;
            case LogLevel::ERROR: level_str = "ERROR"; break;
            case LogLevel::FATAL: level_str = "FATAL"; break;
        }
        
        // 構(gòu)建日志消息
        std::stringstream ss;
        ss << "[" << time_buffer << "." 
           << std::setfill('0') << std::setw(3) << now_ms.count() << "] "
           << "[" << level_str << "] ";
        
        if (file != nullptr) {
            ss << "[" << file << ":" << line << "] ";
        }
        
        ss << message;
        
        std::string log_message = ss.str();
        
        // 輸出到控制臺(tái)
        if (console_output_) {
            std::ostream& stream = (level >= LogLevel::WARN) ? std::cerr : std::cout;
            stream << log_message << std::endl;
            
            if (level == LogLevel::FATAL) {
                stream << "Fatal error, terminating..." << std::endl;
            }
        }
        
        // 輸出到文件
        if (log_file_.is_open()) {
            log_file_ << log_message << std::endl;
            log_file_.flush();
            
            if (level == LogLevel::FATAL) {
                log_file_ << "Fatal error, terminating..." << std::endl;
                log_file_.flush();
            }
        }
        
        // 如果是致命錯(cuò)誤,終止程序
        if (level == LogLevel::FATAL) {
            std::exit(EXIT_FAILURE);
        }
    }
    
    // 關(guān)閉日志
    void Close() {
        std::lock_guard<std::mutex> lock(log_mutex_);
        if (log_file_.is_open()) {
            log_file_.close();
        }
    }
    
    ~Logger() {
        Close();
    }
};

// 日志宏
#define LOG_DEBUG(msg) Logger::Instance().Log(LogLevel::DEBUG, msg, __FILE__, __LINE__)
#define LOG_INFO(msg)  Logger::Instance().Log(LogLevel::INFO, msg, __FILE__, __LINE__)
#define LOG_WARN(msg)  Logger::Instance().Log(LogLevel::WARN, msg, __FILE__, __LINE__)
#define LOG_ERROR(msg) Logger::Instance().Log(LogLevel::ERROR, msg, __FILE__, __LINE__)
#define LOG_FATAL(msg) Logger::Instance().Log(LogLevel::FATAL, msg, __FILE__, __LINE__)

#endif // LOG_HPP

5.2 Makefile - 構(gòu)建系統(tǒng)

# Makefile for UDP Network System

# Compiler and flags
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra -O2 -pthread
DEBUG_FLAGS = -g -DDEBUG
RELEASE_FLAGS = -O3 -DNDEBUG

# Directories
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
INC_DIR = include

# Source files
SERVER_SRCS = $(SRC_DIR)/UdpServer.cpp $(SRC_DIR)/Main.cpp $(SRC_DIR)/Log.cpp
CLIENT_SRCS = $(SRC_DIR)/UdpClient.cpp
TEST_SRCS = $(SRC_DIR)/TestUdpServer.cpp
INTEGRATION_SRCS = $(SRC_DIR)/IntegrationTest.cpp
NETTEST_SRCS = $(SRC_DIR)/NetworkTestTool.cpp

# Object files
SERVER_OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SERVER_SRCS))
CLIENT_OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(CLIENT_SRCS))
TEST_OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(TEST_SRCS))
INTEGRATION_OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(INTEGRATION_SRCS))
NETTEST_OBJS = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(NETTEST_SRCS))

# Executables
SERVER_EXE = $(BIN_DIR)/udp_server
CLIENT_EXE = $(BIN_DIR)/udp_client
TEST_EXE = $(BIN_DIR)/test_server
INTEGRATION_EXE = $(BIN_DIR)/integration_test
NETTEST_EXE = $(BIN_DIR)/network_test

# Include paths
INCLUDES = -I$(INC_DIR)

# Libraries
LIBS = -lpthread
TEST_LIBS = $(LIBS) -lgtest -lgtest_main

# Default target
all: directories server client

# Create directories
directories:
	@mkdir -p $(OBJ_DIR) $(BIN_DIR)

# Server build
server: $(SERVER_EXE)

$(SERVER_EXE): $(SERVER_OBJS)
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)

# Client build
client: $(CLIENT_EXE)

$(CLIENT_EXE): $(CLIENT_OBJS)
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)

# Test build
test: $(TEST_EXE)

$(TEST_EXE): $(TEST_OBJS)
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(TEST_LIBS)

# Integration test build
integration: $(INTEGRATION_EXE)

$(INTEGRATION_EXE): $(INTEGRATION_OBJS)
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)

# Network test tool build
nettest: $(NETTEST_EXE)

$(NETTEST_EXE): $(NETTEST_OBJS)
	$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS)

# Compile source files
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@

# Debug build
debug: CXXFLAGS += $(DEBUG_FLAGS)
debug: all

# Release build
release: CXXFLAGS += $(RELEASE_FLAGS)
release: all

# Static analysis with cppcheck
check:
	cppcheck --enable=all --suppress=missingIncludeSystem $(SRC_DIR) $(INC_DIR)

# Run tests
run-test: test
	$(TEST_EXE)

run-integration: integration
	$(INTEGRATION_EXE)

# Clean build files
clean:
	rm -rf $(OBJ_DIR) $(BIN_DIR)
	rm -f *.log

# Install system-wide (requires root)
install: release
	cp $(SERVER_EXE) /usr/local/bin/udp_server
	cp $(CLIENT_EXE) /usr/local/bin/udp_client
	chmod +x /usr/local/bin/udp_server /usr/local/bin/udp_client

# Uninstall
uninstall:
	rm -f /usr/local/bin/udp_server /usr/local/bin/udp_client

# Run server
run-server: server
	$(SERVER_EXE) -p 8080

# Run client
run-client: client
	$(CLIENT_EXE) -s 127.0.0.1 -p 8080

# Run network test
run-nettest: nettest
	$(NETTEST_EXE) -s 127.0.0.1 -p 8080 -t latency

# Generate documentation
doc:
	doxygen Doxyfile

# Help
help:
	@echo "Available targets:"
	@echo "  all           - Build server and client (default)"
	@echo "  server        - Build server only"
	@echo "  client        - Build client only"
	@echo "  test          - Build and run unit tests"
	@echo "  integration   - Build integration tests"
	@echo "  nettest       - Build network test tool"
	@echo "  debug         - Build with debug flags"
	@echo "  release       - Build with release flags"
	@echo "  check         - Run static analysis"
	@echo "  run-test      - Run unit tests"
	@echo "  run-integration - Run integration tests"
	@echo "  clean         - Remove build files"
	@echo "  install       - Install system-wide"
	@echo "  uninstall     - Uninstall"
	@echo "  run-server    - Run server on port 8080"
	@echo "  run-client    - Run client connecting to localhost:8080"
	@echo "  run-nettest   - Run network latency test"
	@echo "  doc           - Generate documentation"
	@echo "  help          - Show this help"

.PHONY: all directories server client test integration nettest debug release \
        check run-test run-integration clean install uninstall run-server \
        run-client run-nettest doc help

5.3 完整的UdpServer.hpp

#ifndef UDPSERVER_HPP
#define UDPSERVER_HPP

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <thread>
#include <vector>
#include <memory>
#include <atomic>
#include <functional>
#include <queue>
#include <mutex>
#include <condition_variable>
#include "Log.hpp"

class UdpServer {
protected:
    int port_;                      // 服務(wù)器端口
    int sockfd_;                    // 套接字描述符
    std::atomic<bool> is_running_; // 服務(wù)器運(yùn)行狀態(tài)
    struct sockaddr_in server_addr_; // 服務(wù)器地址結(jié)構(gòu)
    struct sockaddr_in client_addr_; // 客戶端地址結(jié)構(gòu)
    socklen_t client_addr_len_;     // 客戶端地址長(zhǎng)度
    
    // 服務(wù)器配置參數(shù)
    size_t buffer_size_;           // 緩沖區(qū)大小
    int timeout_sec_;              // 接收超時(shí)時(shí)間(秒)
    int timeout_usec_;             // 接收超時(shí)時(shí)間(微秒)
    bool reuse_addr_;              // 是否重用地址
    
public:
    // 構(gòu)造函數(shù)
    explicit UdpServer(int port = 8080);
    
    // 析構(gòu)函數(shù)
    virtual ~UdpServer();
    
    // 禁止拷貝構(gòu)造和賦值
    UdpServer(const UdpServer&) = delete;
    UdpServer& operator=(const UdpServer&) = delete;
    
    // 初始化服務(wù)器
    virtual bool Init();
    
    // 運(yùn)行服務(wù)器
    virtual void Run();
    
    // 停止服務(wù)器
    virtual void Stop();
    
    // 設(shè)置配置參數(shù)
    void SetBufferSize(size_t size) { buffer_size_ = size; }
    void SetTimeout(int sec, int usec = 0) { 
        timeout_sec_ = sec; 
        timeout_usec_ = usec; 
    }
    void SetReuseAddr(bool reuse) { reuse_addr_ = reuse; }
    
    // 獲取服務(wù)器信息
    int GetPort() const { return port_; }
    bool IsRunning() const { return is_running_; }
    
protected:
    // 創(chuàng)建套接字
    virtual bool CreateSocket();
    
    // 綁定地址
    virtual bool BindAddress();
    
    // 設(shè)置套接字選項(xiàng)
    virtual bool SetSocketOptions();
    
    // 處理接收到的數(shù)據(jù)
    virtual void ProcessData(const char* data, ssize_t len, 
                            const struct sockaddr_in& client_addr);
    
    // 發(fā)送響應(yīng)
    virtual bool SendResponse(const char* data, ssize_t len, 
                            const struct sockaddr_in& client_addr);
    
    // 清理資源
    virtual void Cleanup();
};

// 高級(jí)UDP服務(wù)器(帶線程池)
class AdvancedUdpServer : public UdpServer {
private:
    std::vector<std::thread> worker_threads_;
    std::atomic<int> thread_count_;
    int max_workers_;
    
    // 線程池和工作隊(duì)列
    struct Task {
        std::vector<char> data;
        struct sockaddr_in client_addr;
        time_t receive_time;
        
        Task(const std::vector<char>& d, const struct sockaddr_in& addr)
            : data(d), client_addr(addr), receive_time(time(nullptr)) {}
    };
    
    std::queue<Task> task_queue_;
    std::mutex queue_mutex_;
    std::condition_variable queue_cv_;
    std::atomic<bool> workers_running_;
    
public:
    AdvancedUdpServer(int port = 8080, int max_workers = 4);
    ~AdvancedUdpServer() override;
    
    bool Init() override;
    void Run() override;
    void Stop() override;
    
    // 獲取線程池狀態(tài)
    int GetActiveWorkers() const { return thread_count_; }
    size_t GetQueueSize() const { return task_queue_.size(); }
    
private:
    void WorkerThread(int thread_id);
    void ProcessTask(const Task& task, int thread_id);
    
    // 重寫基類方法
    bool SetSocketOptions() override;
    void ProcessData(const char* data, ssize_t len, 
                    const struct sockaddr_in& client_addr) override;
    
    // 任務(wù)調(diào)度
    void AddTask(const std::vector<char>& data, 
                const struct sockaddr_in& client_addr);
};

#endif // UDPSERVER_HPP

5.4 完整的Main.cpp

#include <iostream>
#include <csignal>
#include <cstdlib>
#include <memory>
#include <getopt.h>
#include "UdpServer.hpp"
#include "AdvancedUdpServer.hpp"

// 全局服務(wù)器指針,用于信號(hào)處理
std::unique_ptr<UdpServer> g_server;

// 信號(hào)處理函數(shù)
void SignalHandler(int signal) {
    std::cout << "\nReceived signal " << signal << ", shutting down..." << std::endl;
    if (g_server) {
        g_server->Stop();
    }
}

// 顯示使用幫助
void ShowUsage(const char* program_name) {
    std::cout << "UDP Server v1.0 - High Performance UDP Server Implementation\n";
    std::cout << "Build Date: " << __DATE__ << " " << __TIME__ << "\n\n";
    std::cout << "Usage: " << program_name << " [options]\n\n";
    std::cout << "Options:\n";
    std::cout << "  -p, --port PORT      Server port (default: 8080)\n";
    std::cout << "  -b, --buffer SIZE    Buffer size in bytes (default: 4096)\n";
    std::cout << "  -t, --timeout SEC    Receive timeout in seconds (default: 5)\n";
    std::cout << "  -w, --workers NUM    Number of worker threads (default: 1)\n";
    std::cout << "  -a, --advanced       Use advanced server with thread pool\n";
    std::cout << "  -r, --no-reuse       Disable address reuse\n";
    std::cout << "  -v, --verbose        Enable verbose logging\n";
    std::cout << "  -d, --daemon         Run as daemon\n";
    std::cout << "  -c, --config FILE    Load configuration from file\n";
    std::cout << "  -h, --help           Show this help message\n";
    std::cout << "\nExamples:\n";
    std::cout << "  " << program_name << " -p 9000 -b 8192\n";
    std::cout << "  " << program_name << " --port 8080 --workers 4 --advanced\n";
    std::cout << "  " << program_name << " --daemon --config /etc/udp-server.conf\n";
}

// 服務(wù)器配置結(jié)構(gòu)
struct ServerConfig {
    int port = 8080;
    size_t buffer_size = 4096;
    int timeout_sec = 5;
    int timeout_usec = 0;
    int workers = 1;
    bool advanced = false;
    bool reuse_addr = true;
    bool daemon = false;
    bool verbose = false;
    std::string config_file;
    std::string log_file = "udp_server.log";
    LogLevel log_level = LogLevel::INFO;
};

// 解析命令行參數(shù)
ServerConfig ParseArguments(int argc, char* argv[]) {
    ServerConfig config;
    
    struct option long_options[] = {
        {"port", required_argument, 0, 'p'},
        {"buffer", required_argument, 0, 'b'},
        {"timeout", required_argument, 0, 't'},
        {"workers", required_argument, 0, 'w'},
        {"advanced", no_argument, 0, 'a'},
        {"no-reuse", no_argument, 0, 'r'},
        {"verbose", no_argument, 0, 'v'},
        {"daemon", no_argument, 0, 'd'},
        {"config", required_argument, 0, 'c'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    int option_index = 0;
    
    while ((opt = getopt_long(argc, argv, "p:b:t:w:arvdc:h", 
                              long_options, &option_index)) != -1) {
        switch (opt) {
            case 'p':
                config.port = std::atoi(optarg);
                if (config.port <= 0 || config.port > 65535) {
                    std::cerr << "Error: Port must be between 1 and 65535" << std::endl;
                    exit(EXIT_FAILURE);
                }
                break;
            case 'b':
                config.buffer_size = std::atoi(optarg);
                if (config.buffer_size < 1024 || config.buffer_size > 65536) {
                    std::cerr << "Error: Buffer size must be between 1024 and 65536" << std::endl;
                    exit(EXIT_FAILURE);
                }
                break;
            case 't':
                config.timeout_sec = std::atoi(optarg);
                if (config.timeout_sec < 0) {
                    std::cerr << "Error: Timeout must be non-negative" << std::endl;
                    exit(EXIT_FAILURE);
                }
                break;
            case 'w':
                config.workers = std::atoi(optarg);
                if (config.workers < 1 || config.workers > 32) {
                    std::cerr << "Error: Number of workers must be between 1 and 32" << std::endl;
                    exit(EXIT_FAILURE);
                }
                break;
            case 'a':
                config.advanced = true;
                break;
            case 'r':
                config.reuse_addr = false;
                break;
            case 'v':
                config.verbose = true;
                config.log_level = LogLevel::DEBUG;
                break;
            case 'd':
                config.daemon = true;
                break;
            case 'c':
                config.config_file = optarg;
                // 這里可以添加從配置文件加載配置的邏輯
                break;
            case 'h':
                ShowUsage(argv[0]);
                exit(EXIT_SUCCESS);
            default:
                std::cerr << "Error: Unknown option" << std::endl;
                ShowUsage(argv[0]);
                exit(EXIT_FAILURE);
        }
    }
    
    return config;
}

// 守護(hù)進(jìn)程化
void Daemonize() {
    pid_t pid = fork();
    
    if (pid < 0) {
        std::cerr << "Failed to fork daemon: " << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }
    
    if (pid > 0) {
        // 父進(jìn)程退出
        exit(EXIT_SUCCESS);
    }
    
    // 子進(jìn)程繼續(xù)
    umask(0);
    
    pid_t sid = setsid();
    if (sid < 0) {
        std::cerr << "Failed to create new session: " << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }
    
    if ((chdir("/")) < 0) {
        std::cerr << "Failed to change directory: " << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }
    
    // 關(guān)閉標(biāo)準(zhǔn)文件描述符
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    
    // 重定向到/dev/null
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_WRONLY);
    open("/dev/null", O_RDWR);
}

int main(int argc, char* argv[]) {
    // 解析命令行參數(shù)
    ServerConfig config = ParseArguments(argc, argv);
    
    // 如果需要,轉(zhuǎn)換為守護(hù)進(jìn)程
    if (config.daemon) {
        Daemonize();
    }
    
    // 注冊(cè)信號(hào)處理
    signal(SIGINT, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGPIPE, SIG_IGN);  // 忽略管道破裂信號(hào)
    
    try {
        if (!config.daemon) {
            std::cout << "=== UDP Server Starting ===\n";
            std::cout << "Version: 1.0\n";
            std::cout << "Port: " << config.port << "\n";
            std::cout << "Buffer size: " << config.buffer_size << " bytes\n";
            std::cout << "Timeout: " << config.timeout_sec << " seconds\n";
            std::cout << "Workers: " << config.workers << "\n";
            std::cout << "Mode: " << (config.advanced ? "Advanced (Thread Pool)" : "Basic") << "\n";
            std::cout << "Log file: " << config.log_file << "\n";
            std::cout << "Log level: " << (config.verbose ? "DEBUG" : "INFO") << "\n";
            std::cout << "===========================\n\n";
        }
        
        // 初始化日志系統(tǒng)
        Logger::Instance().Init(config.log_file, config.log_level, !config.daemon);
        LOG_INFO("UDP Server starting...");
        LOG_INFO("Configuration: port=%d, buffer=%zu, timeout=%d, workers=%d, mode=%s",
                config.port, config.buffer_size, config.timeout_sec, 
                config.workers, config.advanced ? "advanced" : "basic");
        
        // 創(chuàng)建服務(wù)器實(shí)例
        if (config.advanced) {
            g_server = std::make_unique<AdvancedUdpServer>(config.port, config.workers);
        } else {
            g_server = std::make_unique<UdpServer>(config.port);
        }
        
        // 配置服務(wù)器
        g_server->SetBufferSize(config.buffer_size);
        g_server->SetTimeout(config.timeout_sec, config.timeout_usec);
        g_server->SetReuseAddr(config.reuse_addr);
        
        // 初始化服務(wù)器
        if (!g_server->Init()) {
            LOG_FATAL("Failed to initialize server");
            return EXIT_FAILURE;
        }
        
        LOG_INFO("Server initialized successfully");
        
        if (!config.daemon) {
            std::cout << "Server initialized successfully\n";
            std::cout << "Press Ctrl+C to stop the server\n\n";
        }
        
        // 運(yùn)行服務(wù)器
        g_server->Run();
        
    } catch (const std::exception& e) {
        LOG_ERROR("Exception: %s", e.what());
        if (!config.daemon) {
            std::cerr << "Exception: " << e.what() << std::endl;
        }
        return EXIT_FAILURE;
    } catch (...) {
        LOG_ERROR("Unknown exception occurred");
        if (!config.daemon) {
            std::cerr << "Unknown exception occurred" << std::endl;
        }
        return EXIT_FAILURE;
    }
    
    LOG_INFO("Server stopped gracefully");
    if (!config.daemon) {
        std::cout << "\nServer stopped gracefully" << std::endl;
    }
    
    return EXIT_SUCCESS;
}

總結(jié)

通過(guò)本文的詳細(xì)講解和代碼實(shí)現(xiàn),我們完成了一個(gè)完整的UDP網(wǎng)絡(luò)通信系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)。這個(gè)系統(tǒng)具有以下特點(diǎn)和優(yōu)勢(shì):

1. 系統(tǒng)架構(gòu)特點(diǎn)

模塊化設(shè)計(jì)

  • 服務(wù)器和客戶端分離,職責(zé)明確
  • 日志系統(tǒng) 獨(dú)立,便于維護(hù)和擴(kuò)展
  • 配置系統(tǒng)靈活,支持命令行和配置文件

高性能設(shè)計(jì)

  • 支持多線程處理,充分利用多核CPU
  • 智能緩沖區(qū)管理,避免內(nèi)存碎片
  • 異步I/O操作,減少等待時(shí)間

可靠性保障

  • 完善的錯(cuò)誤處理和異?;謴?fù)機(jī)制
  • 連接狀態(tài)監(jiān)控和自動(dòng)清理
  • 詳細(xì)的日志記錄,便于問(wèn)題排查

2. 關(guān)鍵技術(shù)點(diǎn)

套接字編程核心

  • 深入理解了socket()、bind()、recvfrom()、sendto()等系統(tǒng)調(diào)用
  • 掌握了地址轉(zhuǎn)換函數(shù)如inet_pton()inet_ntop()的使用
  • 理解了字節(jié)序轉(zhuǎn)換的重要性

并發(fā)處理

  • 多線程編程的最佳實(shí)踐
  • 線程安全的隊(duì)列實(shí)現(xiàn)
  • 條件變量的正確使用

網(wǎng)絡(luò)優(yōu)化

  • 緩沖區(qū)大小的優(yōu)化配置
  • 超時(shí)機(jī)制的合理設(shè)置
  • 數(shù)據(jù)包分片和重組處理

3. 實(shí)際應(yīng)用價(jià)值

教育意義

  • 完整的網(wǎng)絡(luò)編程教學(xué)示例
  • 良好的編碼規(guī)范和架構(gòu)設(shè)計(jì)示范
  • 詳細(xì)的注釋和文檔說(shuō)明

實(shí)用價(jià)值

  • 可直接用于實(shí)際項(xiàng)目的網(wǎng)絡(luò)通信模塊
  • 提供了性能測(cè)試和監(jiān)控工具
  • 支持多種運(yùn)行模式和配置選項(xiàng)

擴(kuò)展性

  • 易于添加新的協(xié)議支持
  • 支持插件式功能擴(kuò)展
  • 良好的接口設(shè)計(jì),便于二次開(kāi)發(fā)

4. 性能優(yōu)化建議

服務(wù)器端優(yōu)化

  • 使用epoll或kqueue等I/O多路復(fù)用技術(shù)處理更多并發(fā)連接
  • 實(shí)現(xiàn)連接池減少連接建立開(kāi)銷
  • 使用內(nèi)存池技術(shù)減少內(nèi)存分配開(kāi)銷

客戶端優(yōu)化

  • 實(shí)現(xiàn)請(qǐng)求合并,減少網(wǎng)絡(luò)包數(shù)量
  • 添加壓縮支持,減少數(shù)據(jù)傳輸量
  • 實(shí)現(xiàn)智能重傳機(jī)制,提高可靠性

網(wǎng)絡(luò)優(yōu)化

  • 支持IPv6雙棧
  • 添加QUIC協(xié)議支持
  • 實(shí)現(xiàn)流量控制和擁塞避免算法

5. 安全考慮

基礎(chǔ)安全

  • 輸入驗(yàn)證和邊界檢查
  • 緩沖區(qū)溢出防護(hù)
  • 資源限制和配額管理

高級(jí)安全

  • 支持TLS/DTLS加密傳輸
  • 實(shí)現(xiàn)身份驗(yàn)證和授權(quán)機(jī)制
  • 添加DoS攻擊防護(hù)

6. 未來(lái)發(fā)展方向

功能增強(qiáng)

  • 添加Web管理界面
  • 支持集群部署
  • 實(shí)現(xiàn)負(fù)載均衡

性能提升

  • 支持RDMA高速網(wǎng)絡(luò)
  • 添加GPU加速支持
  • 實(shí)現(xiàn)零拷貝技術(shù)

生態(tài)系統(tǒng)

  • 提供多種語(yǔ)言SDK
  • 支持云原生部署
  • 集成監(jiān)控告警系統(tǒng)

通過(guò)本系統(tǒng)的實(shí)現(xiàn),讀者不僅能夠掌握UDP網(wǎng)絡(luò)編程的核心技術(shù),還能夠?qū)W習(xí)到軟件工程中的良好實(shí)踐,包括模塊化設(shè)計(jì)、錯(cuò)誤處理、性能優(yōu)化、測(cè)試策略等。這個(gè)系統(tǒng)可以作為學(xué)習(xí)網(wǎng)絡(luò)編程的絕佳范例,也可以作為實(shí)際項(xiàng)目的基礎(chǔ)框架進(jìn)行擴(kuò)展和優(yōu)化。

網(wǎng)絡(luò)編程是一個(gè)既深又廣的領(lǐng)域,本文只是拋磚引玉。希望讀者能夠在此基礎(chǔ)上繼續(xù)探索,深入研究網(wǎng)絡(luò)協(xié)議的各個(gè)層面,從應(yīng)用層到底層實(shí)現(xiàn),不斷積累經(jīng)驗(yàn),最終成為網(wǎng)絡(luò)編程的專家。

以上就是基于C++的UDP網(wǎng)絡(luò)通信系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ UDP網(wǎng)絡(luò)通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • visual?studio?2022?編譯出來(lái)的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)

    visual?studio?2022?編譯出來(lái)的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)

    這篇文章主要介紹了visual?studio?2022?編譯出來(lái)的文件被刪除?并監(jiān)視目錄中的文件變更,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 基于SVN源碼服務(wù)器搭建(詳細(xì)教程分析)

    基于SVN源碼服務(wù)器搭建(詳細(xì)教程分析)

    本篇文章是對(duì)SVN源碼服務(wù)器搭建進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • C語(yǔ)言常用標(biāo)準(zhǔn)頭文件使用實(shí)例

    C語(yǔ)言常用標(biāo)準(zhǔn)頭文件使用實(shí)例

    在C的系列語(yǔ)言程序中,頭文件(通常擴(kuò)展名為.h)被大量使用,它通常包含函數(shù)、變量、結(jié)構(gòu)體等的聲明和定義,以及一些宏定義和類型定義,這篇文章主要給大家介紹了關(guān)于C語(yǔ)言常用標(biāo)準(zhǔn)頭文件使用的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • 淺談C++中對(duì)象的復(fù)制與對(duì)象之間的相互賦值

    淺談C++中對(duì)象的復(fù)制與對(duì)象之間的相互賦值

    這篇文章主要介紹了淺談C++中對(duì)象的復(fù)制與對(duì)象之間的相互賦值,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C++中map和set的簡(jiǎn)介及使用詳解

    C++中map和set的簡(jiǎn)介及使用詳解

    本文主要介紹了C++中map和set的簡(jiǎn)介及使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C和C++ const的聲明差異

    C和C++ const的聲明差異

    本文給大家簡(jiǎn)單匯總了下C語(yǔ)言的const與C++的const的聲明差異,非常的簡(jiǎn)單,也很實(shí)用,有需要的小伙伴可以參考下
    2016-03-03
  • 詳解C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn)

    詳解C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn)

    這篇文章主要介紹了C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn),建造者模式將一個(gè)復(fù)雜對(duì)象的構(gòu)建于它的表現(xiàn)分離,可以減少代碼冗余,需要的朋友可以參考下
    2016-03-03
  • C++中的vector中erase用法實(shí)例代碼

    C++中的vector中erase用法實(shí)例代碼

    在vector數(shù)組中我們刪除數(shù)組經(jīng)常用的就是erase方法,但是earse的用法一不注意就會(huì)出錯(cuò),今天我就遇到了,所以在這里總結(jié)一下,避免大家用錯(cuò),對(duì)vector中erase用法感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • C++實(shí)例輸入多行數(shù)字到數(shù)組

    C++實(shí)例輸入多行數(shù)字到數(shù)組

    這篇文章主要介紹了C++實(shí)例輸入多行數(shù)字到數(shù)組的相關(guān)資料,這里提供實(shí)例代碼幫助大家學(xué)習(xí)理解,需要的朋友可以參考下
    2016-12-12
  • C++實(shí)現(xiàn)LeetCode(71.簡(jiǎn)化路徑)

    C++實(shí)現(xiàn)LeetCode(71.簡(jiǎn)化路徑)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(71.簡(jiǎn)化路徑),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評(píng)論

英德市| 汽车| 广宁县| 离岛区| 原阳县| 松阳县| 清新县| 罗山县| 衡山县| 右玉县| 东兴市| 平度市| 双峰县| 宁武县| 星座| 郎溪县| 五大连池市| 尖扎县| 睢宁县| 六枝特区| 赣州市| 曲松县| 鄂托克前旗| 丰顺县| 姚安县| 礼泉县| 正蓝旗| 禄丰县| 祥云县| 教育| 吉首市| 金沙县| 文山县| 依兰县| 西峡县| 如东县| 中阳县| 青铜峡市| 涟水县| 土默特右旗| 方城县|