Skip to content

NET_SocketConnection

SweerItTer edited this page Feb 21, 2026 · 1 revision

SocketConnection

概述

SocketConnection 是 Socket 连接管理类,负责单个客户端 TCP 连接的生命周期管理。专注连接处理,命令解析和执行委托给 TcpServer

类定义

class SocketConnection : public std::enable_shared_from_this<SocketConnection> {
public:
    SocketConnection(int clientFd, uint64_t clientId,
                     const std::string& clientIp, uint16_t clientPort,
                     std::weak_ptr<TcpServer> server);
    ~SocketConnection();

    // 禁止拷贝,允许移动
    SocketConnection(const SocketConnection&) = delete;
    SocketConnection& operator=(const SocketConnection&) = delete;
    SocketConnection(SocketConnection&& other) noexcept;
    SocketConnection& operator=(SocketConnection&& other) noexcept;

    // 连接控制
    void startReceiveLoop();
    void stopReceiveLoop();
    void disconnect();

    // 数据发送
    bool send(const DataPacket& packet);

    // 状态查询
    uint64_t getClientId() const;
    const std::string& getClientIp() const;
    uint16_t getClientPort() const;
    ConnectionState getState() const;
    bool isValid() const;

    // 文件描述符
    int getFd() const;

    // 统计信息
    uint64_t getReceivedBytes() const;
    uint64_t getSentBytes() const;
    const std::string& getLastError() const;

private:
    void receiveLoop();
    void sendLoop();
    void setKeepAliveOptions();
    bool sendText(const std::string& data);
    bool sendFd(int fd);
    std::pair<std::string, std::string> parseReceivedData(const std::string& data);
};

公共方法

构造/析构

SocketConnection(int clientFd, uint64_t clientId, const std::string& clientIp, uint16_t clientPort, std::weak_ptr server)

描述: 构造 Socket 连接对象。

参数:

  • clientFd: 客户端 socket 文件描述符
  • clientId: 客户端唯一 ID
  • clientIp: 客户端 IP 地址
  • clientPort: 客户端端口号
  • server: 服务器弱引用(用于回调,通过 weak_ptr.lock() 安全访问)

示例:

// 通常由 TcpServer 通过工厂函数创建,无需手动调用
// TcpServer::createConnection() 为私有成员函数
// 内部会使用 shared_from_this() 获取有效的 shared_ptr
auto conn = server->createConnection(clientFd, clientId, "192.168.1.100", 12345);

~SocketConnection()

描述: 析构函数,自动关闭连接并清理资源。

连接控制

void startReceiveLoop()

描述: 启动接收循环(非阻塞,在独立线程中运行)。

行为:

  • 创建接收线程
  • 持续监听客户端数据
  • 解析命令并委托给 TcpServer 执行
  • 发送响应给客户端

示例:

conn->startReceiveLoop();

void stopReceiveLoop()

描述: 停止接收循环。

行为:

  • 停止接收线程
  • 清空发送队列
  • 断开连接

示例:

conn->stopReceiveLoop();

void disconnect()

描述: 断开连接。

行为:

  • 关闭 socket
  • 清理资源
  • 通知服务器

数据发送

bool send(const DataPacket& packet)

描述: 发送数据(异步,进入发送队列)。

参数:

  • packet: 数据包

返回值:

  • true: 数据已加入发送队列
  • false: 发送失败(队列满或连接已断开)

支持的数据类型:

  • PacketType::TEXT: 普通文本
  • PacketType::DMABUF_FD: DMA-BUF(零拷贝)
  • PacketType::RAW_FD: 裸文件描述符

示例:

// 发送文本
conn->send(DataPacket::createText("Hello"));

// 发送 DMA-BUF(零拷贝)
DmaBufferPtr dmabuf = DmaBuffer::create(1920, 1080, DRM_FORMAT_ARGB8888);
conn->send(DataPacket::createDmaBuf(dmabuf));

状态查询

uint64_t getClientId() const

描述: 获取客户端 ID。

返回值: 客户端唯一 ID

const std::string& getClientIp() const

描述: 获取客户端 IP 地址。

返回值: IP 地址字符串

uint16_t getClientPort() const

描述: 获取客户端端口号。

返回值: 端口号

ConnectionState getState() const

描述: 获取连接状态。

返回值: 连接状态枚举

状态值:

  • ConnectionState::CONNECTED: 已连接
  • ConnectionState::DISCONNECTED: 已断开
  • ConnectionState::ERROR: 错误状态

bool isValid() const

描述: 检查连接是否有效。

返回值:

  • true: 连接有效
  • false: 连接无效

int getFd() const

描述: 获取 socket 文件描述符。

返回值: socket fd

统计信息

uint64_t getReceivedBytes() const

描述: 获取接收的字节数统计。

返回值: 总接收字节数

uint64_t getSentBytes() const

描述: 获取发送的字节数统计。

返回值: 总发送字节数

const std::string& getLastError() const

描述: 获取最后的错误信息。

返回值: 错误信息字符串

内部实现

接收循环

接收线程
  ├─ recv() 阻塞等待数据
  ├─ 解析命令(格式:COMMAND PARAMS)
  ├─ 委托给 TcpServer::executeCommand
  ├─ 发送响应给客户端
  └─ 循环

发送循环

发送线程
  ├─ 从发送队列取数据
  ├─ 类型判断
  │   ├─ TEXT -> send()
  │   ├─ DMABUF_FD -> sendmsg() + SCM_RIGHTS
  │   └─ RAW_FD -> sendmsg() + SCM_RIGHTS
  └─ 循环

Keep-Alive

TCP Keep-Alive 选项用于检测死连接:

  • TCP_KEEPIDLE: 空闲 60 秒后开始探测
  • TCP_KEEPINTVL: 每 10 秒探测一次
  • TCP_KEEPCNT: 最多探测 5 次

使用示例

基本使用(通常由 TcpServer 管理)

// TcpServer 内部自动创建和管理 SocketConnection
// 无需手动创建和销毁

// 访问连接信息
uint64_t clientId = conn->getClientId();
std::string ip = conn->getClientIp();
uint16_t port = conn->getClientPort();

// 发送数据
conn->send(DataPacket::createText("Hello"));

// 断开连接
conn->disconnect();

检查连接状态

if (conn->isValid() && conn->getState() == ConnectionState::CONNECTED) {
    // 连接有效
    conn->send(DataPacket::createText("Ping"));
} else {
    // 连接无效
    std::cout << "Connection error: " << conn->getLastError() << std::endl;
}

统计信息

std::cout << "Client: " << conn->getClientIp() << ":" << conn->getClientPort() << std::endl;
std::cout << "Received: " << conn->getReceivedBytes() << " bytes" << std::endl;
std::cout << "Sent: " << conn->getSentBytes() << " bytes" << std::endl;

命令处理流程

客户端发送命令

Client: GETFILENAME /path/to/file.txt

SocketConnection 解析

void SocketConnection::parseReceivedData(const std::string& data) {
    if (data.empty() || !server_) {
        return;
    }

    // 解析命令格式: COMMAND PARAMS
    std::string command;
    std::string params;
    size_t spacePos = data.find(' ');
    if (spacePos != std::string::npos) {
        command = data.substr(0, spacePos);
        params = data.substr(spacePos + 1);
    } else {
        command = data;
        params = "";
    }

    // 委托给 TcpServer 执行命令
    std::string commandResult = server_->executeCommand(clientId_, command, params);

    // 发送响应
    if (!commandResult.empty()) {
        sendText(commandResult + "\n");
    }
}

TcpServer 委托给 CommandHandler

std::string TcpServer::executeCommand(uint64_t clientId,
                                      const std::string& command,
                                      const std::string& params) {
    auto commandHandler = commandHandler_.lock();
    if (!commandHandler) {
        return "";  // Command handler expired
    }
    return commandHandler->executeCommand(clientId, command, params);
}

CommandHandler 执行回调

std::string CommandHandler::executeCommand(uint64_t clientId,
                                           const std::string& command,
                                           const std::string& params) {
    std::lock_guard<std::mutex> lock(registryMutex_);

    auto it = commandRegistry_.find(command);
    if (it == commandRegistry_.end()) {
        return "";  // Command not found
    }

    try {
        return it->second.callback(clientId, command, params);
    } catch (const std::exception& e) {
        fprintf(stderr, "[CommandHandler] Exception: %s\n", e.what());
        return std::string("ERROR: ") + e.what();
    }
}

错误处理

连接断开

当连接断开时:

  1. 接收线程自动退出
  2. 发送队列清空
  3. 状态更新为 DISCONNECTED
  4. 服务器收到通知并移除客户端

错误信息

通过 getLastError() 获取详细错误信息:

if (!conn->send(DataPacket::createText("Hello"))) {
    std::cerr << "Send failed: " << conn->getLastError() << std::endl;
}

线程安全

  • 接收线程: 独立线程,处理接收和命令解析
  • 发送线程: 独立线程,处理发送队列
  • 线程安全: 使用互斥锁保护共享数据(状态、队列等)

性能优化

  1. 异步发送: 数据进入队列立即返回,不阻塞调用者
  2. 零拷贝: DMA-BUF 直接发送,无需内存拷贝
  3. 批量处理: 发送队列支持批量处理,减少系统调用

相关类

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally