跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++

C++ 从零实现 TCP Socket 网络通信工具

综述由AI生成基于 C++ 标准库封装 TCP Socket 网络通信类,涵盖 socket、bind、listen 等核心接口详解及完整代码示例。文章详细解析了各函数的参数含义与返回值处理,并通过 Sock 类演示了如何构建可复用的网络组件,适合希望深入理解 Linux 网络编程的开发者参考。

猫巷少女发布于 2026/3/15更新于 2026/4/274 浏览
C++ 从零实现 TCP Socket 网络通信工具

C++ 从零实现 TCP Socket 网络通信工具

前言

网络编程中的套接字(Socket)是通信的基本接口,允许不同计算机之间通过网络交换数据。它作为计算机网络中通信的'端点',为应用程序提供了与网络中其他计算机进行数据通信的能力。网络套接字接口提供了一种抽象的、平台无关的方式来进行进程间通信(IPC)或网络通信。

核心头文件

编写网络程序主要依赖四个核心头文件,绝大多数常用函数都定义其中:

#include <sys/types.h>   // 包含各种系统数据类型
#include <sys/socket.h>  // 包含套接字操作相关函数和常量
#include <arpa/inet.h>   // 包含与 Internet 地址转换相关的函数
#include <netinet/in.h>  // 定义与网络字节序及 IPv4/IPv6 地址相关的结构体和常量

基础 API 详解

socket

socket() 函数是创建网络通信套接字的基础。它用于创建一个套接字并返回一个描述符,后续所有操作都基于此描述符。

int socket(int domain, int type, int protocol);

参数解析:

  • domain(地址族):指定通信协议族。常用 AF_INET(IPv4)、AF_INET6(IPv6)或 AF_UNIX(本地通信)。
  • type(套接字类型):决定数据传输方式。SOCK_STREAM 对应 TCP,SOCK_DGRAM 对应 UDP,SOCK_RAW 用于底层协议。
  • protocol:指定具体协议,通常设为 0 让系统自动选择(如 TCP 时选 IPPROTO_TCP)。

返回结果: 成功返回非负整数描述符;失败返回 -1 并设置 errno。

bind

将套接字绑定到指定的本地地址(IP 和端口)。服务器端必须调用此函数。

int bind;
(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

关键点:

  • sockfd:socket() 创建的描述符。
  • addr:指向 struct sockaddr 或其子类(如 sockaddr_in)的指针,包含 IP 和端口信息。
  • addrlen:地址结构体的大小,通常为 sizeof(struct sockaddr_in)。

返回结果: 成功返回 0,失败返回 -1。

listen

将主动套接字转换为被动监听套接字,准备接受客户端连接请求。

int listen(int sockfd, int backlog);

参数说明:

  • backlog:监听队列的最大长度。当多个客户端同时请求连接时,超出此数量的请求会被拒绝或丢弃。一般设置为 5 到 128,高并发场景可适当调大。

返回结果: 成功返回 0,失败返回 -1。

accept

阻塞等待并接受客户端的连接请求。一旦连接建立,会返回一个新的套接字描述符用于与该客户端通信。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

注意:

  • 原始监听套接字继续用于 accept,新返回的描述符才用于 send/recv。
  • 通过 addr 参数可以获取客户端的 IP 和端口信息。

返回结果: 成功返回新套接字描述符,失败返回 -1。

connect

客户端发起连接请求,尝试与远程服务器建立 TCP 连接。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

流程:

  1. 构造目标服务器的 sockaddr_in 结构体。
  2. 调用 connect() 发起三次握手。
  3. 若连接成功返回 0,否则返回 -1。

close

关闭套接字描述符,释放相关资源。

int close(int fd);

务必在程序退出前关闭所有打开的套接字,防止资源泄漏。

C++ 封装实现

理解了基础 API 后,我们可以将其封装为 C++ 类,提高代码的可读性和复用性。下面是一个简单的 Sock 类实现示例。

头文件引用

#include <iostream>
#include <string>
#include <cstring>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
// log.hpp 为项目自定义日志头文件
#include "log.hpp"

全局配置与错误枚举

int backlog = 10;
enum err {
    Socketerr = 1,
    Bindeterr,
    Listeneterr,
    Accepteterr,
};

这里定义了监听队列长度和常见的错误码枚举,便于统一处理异常。

Sock 类设计

构造函数与析构函数
Sock() {}
~Sock() {}

默认构造函数不执行初始化,析构函数预留资源清理逻辑(实际项目中建议在此处调用 close())。

Socket - 创建套接字
void Socket() {
    sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd_ < 0) {
        lg(FATAL, "Socket error: %d,%s", errno, strerror(errno));
        exit(Socketerr);
    }
}

使用 AF_INET 和 SOCK_STREAM 创建 IPv4 TCP 套接字。若创建失败直接记录日志并退出。

Bind - 绑定地址
void Bind(uint16_t port) {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    bzero(&peer, len);
    
    peer.sin_port = htons(port);       // 主机序转网络序
    peer.sin_family = AF_INET;
    peer.sin_addr.s_addr = INADDR_ANY; // 绑定所有可用网卡

    if (bind(sockfd_, (struct sockaddr*)&(peer), len) < 0) {
        lg(FATAL, "Bind error: %d,%s", errno, strerror(errno));
        exit(Bindeterr);
    }
}

注意端口号需通过 htons() 转换字节序,INADDR_ANY 表示监听本机所有 IP。

Listen - 开始监听
void Listen() {
    if (listen(sockfd_, backlog) < 0) {
        lg(FATAL, "Listen error: %d,%s", errno, strerror(errno));
        exit(Listeneterr);
    }
}

将套接字置为监听状态,进入等待连接阶段。

Accept - 接受连接
int Accept(std::string *clientip, uint16_t *clientport) {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    bzero(&peer, len);

    int newfd = accept(sockfd_, (struct sockaddr*)&(peer), &len);
    if (newfd < 0) {
        lg(FATAL, "Accept error: %d,%s", errno, strerror(errno));
        exit(Accepteterr);
    }

    char ip[64];
    inet_ntop(AF_INET, &peer.sin_addr.s_addr, ip, sizeof(ip));
    *clientip = ip;
    *clientport = ntohs(peer.sin_port);
    return newfd;
}

获取新连接描述符,并将客户端 IP 和端口转换为可读字符串返回。

Connect - 连接服务器
bool Connect(const std::string& ip, const uint16_t& port) {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    bzero(&peer, len);
    
    peer.sin_addr.s_addr = inet_addr(ip.c_str());
    peer.sin_port = htons(port);
    peer.sin_family = AF_INET;

    int n = connect(sockfd_, (struct sockaddr*)&(peer), len);
    if (n < 0) {
        lg(WARNING, "Connect error: %d,%s", errno, strerror(errno));
        return false;
    }
    return true;
}

客户端专用方法,将 IP 字符串转为二进制格式后发起连接。

GetFd - 获取描述符
int GetFd() {
    return sockfd_;
}

提供访问内部描述符的接口,方便外部调用 send/recv 等底层函数。


以上代码展示了从底层 API 到面向对象封装的完整过程。在实际开发中,建议结合 RAII 机制管理资源,并在析构函数中确保 close() 被正确调用。

目录

  1. C++ 从零实现 TCP Socket 网络通信工具
  2. 前言
  3. 核心头文件
  4. 基础 API 详解
  5. socket
  6. bind
  7. listen
  8. accept
  9. connect
  10. close
  11. C++ 封装实现
  12. 头文件引用
  13. 全局配置与错误枚举
  14. Sock 类设计
  15. 构造函数与析构函数
  16. Socket - 创建套接字
  17. Bind - 绑定地址
  18. Listen - 开始监听
  19. Accept - 接受连接
  20. Connect - 连接服务器
  21. GetFd - 获取描述符
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 滑动窗口算法详解:经典例题解析
  • 复制带随机指针的链表:LeetCode 138 题解法
  • Linux 进程信号入门:软中断机制与实战
  • Go2 机器人 ROS2 与 Gazebo 仿真环境搭建指南
  • WebMCP:浏览器 AI 交互新范式
  • SeaTunnel 2.3.11 + Web 1.0.3 Docker 部署及 Kafka 同步 Hive/ES 指南
  • 从 Webhook 到 AI Agent:钉钉周报机器人演进实践
  • AI 视频生成模型构建、实现与调试指南
  • Milvus 实战:Attu 可视化安装与 Python 整合指南
  • Mac 专属大模型框架 Chat with MLX:两行代码部署与本地数据对话
  • 医疗 AI 场景下算法编程深度解析
  • ChatGLM-6B 使用、微调与训练指南
  • Python 调用 Ollama 本地大模型 API 完全指南
  • C++ 汉诺塔问题详解与代码实现
  • Open-Lovable 网页克隆实战与 cpolar 远程访问配置
  • C++ 智能指针详解:原理、实现与内存安全
  • 国内升级 GitHub Copilot 专业版:PayPal 支付方案详解
  • 大模型技术实战指南:从基础理论到应用开发
  • MacBook 手动安装多版本 JDK(8 和 17)并配置灵活切换
  • YOLOv8 旋转框角度回归优化:CSL 与 DCL 编码实战

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online