跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++网络编程:TCP服务器与客户端实现

C++网络编程涉及TCP/IP协议、套接字编程及Boost.Asio库应用。通过基础与多线程服务器、客户端代码示例,演示TCP连接、数据收发及错误处理流程。综合案例展示基于Boost.Asio的聊天服务器实现,包含项目结构、核心类设计与构建运行步骤,旨在帮助开发者掌握高效稳定的网络应用开发技能。

乱七八糟发布于 2026/3/16更新于 2026/10/2192 浏览
C++网络编程:TCP服务器与客户端实现

C++网络编程:TCP服务器与客户端实现

一、学习目标与重点

本章将深入探讨C++网络编程的核心知识,帮助你掌握TCP服务器与客户端的实现。通过学习,你将能够:

  1. 理解网络编程的基本概念,掌握TCP/IP协议的核心要点
  2. 学会使用套接字编程,实现简单的TCP服务器与客户端
  3. 理解网络编程中的错误处理,提高程序的健壮性
  4. 学会使用Boost.Asio库,简化网络编程的复杂流程
  5. 培养网络编程思维,设计高效且稳定的网络应用

二、网络编程基础

2.1 TCP/IP协议简介

TCP/IP(传输控制协议/互联网协议)是互联网的核心协议,它提供了可靠的、面向连接的通信服务。TCP协议确保数据的可靠传输,通过三次握手建立连接,四次挥手关闭连接。

2.2 套接字编程基础

套接字(Socket)是网络编程的基础,它提供了进程间通信的接口。在C++中,可以使用<sys/socket.h>头文件提供的套接字API进行网络编程。

三、TCP服务器的实现

3.1 基本服务器结构
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>

const int PORT = 8080;
const int BUFFER_SIZE = 1024;

int main() {
    std::cout << "=== TCP服务器示例 ===" << std::endl;
    // 1. 创建套接字
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        std::cerr << "套接字创建失败" << std::endl;
        return 1;
    }
    // 2. 设置套接字选项,允许地址复用
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        std::cerr << "设置套接字选项失败" << std::endl;
        close(server_fd);
        return 1;
    }
    // 3. 绑定地址和端口
    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
        std::cerr << "绑定地址和端口失败" << std::endl;
        close(server_fd);
        return 1;
    }
    // 4. 监听连接
    if (listen(server_fd, 3) < 0) {
        std::cerr << "监听连接失败" << std::endl;
        close(server_fd);
        return 1;
    }
    std::cout << "服务器正在监听端口 " << PORT << "..." << std::endl;
    // 5. 接受连接
    int addrlen = sizeof(address);
    int new_socket;
    while (true) {
        std::cout << "等待客户端连接..." << std::endl;
        new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            std::cerr << "接受连接失败" << std::endl;
            continue;
        }
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &address.sin_addr, client_ip, INET_ADDRSTRLEN);
        std::cout << "客户端 " << client_ip << " 已连接" << std::endl;
        // 6. 处理连接
        char buffer[BUFFER_SIZE] = {0};
        int valread = read(new_socket, buffer, BUFFER_SIZE);
        if (valread < 0) {
            std::cerr << "读取数据失败" << std::endl;
            close(new_socket);
            continue;
        }
        std::cout << "收到来自客户端的消息:" << buffer << std::endl;
        // 7. 发送响应
        std::string response = "服务器已收到消息:" + std::string(buffer);
        send(new_socket, response.c_str(), response.length(), 0);
        std::cout << "响应已发送" << std::endl;
        // 8. 关闭连接
        close(new_socket);
        std::cout << "客户端连接已关闭" << std::endl;
    }
    // 9. 关闭服务器套接字
    close(server_fd);
    return 0;
}
3.2 多线程服务器
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <vector>

const int PORT = 8080;
const int BUFFER_SIZE = 1024;

void handleClient(int client_socket, const std::string& client_ip) {
    char buffer[BUFFER_SIZE] = {0};
    while (true) {
        int valread = read(client_socket, buffer, BUFFER_SIZE);
        if (valread < 0) {
            std::cerr << "客户端 " << client_ip << " 读取数据失败" << std::endl;
            break;
        } else if (valread == 0) {
            std::cout << "客户端 " << client_ip << " 已断开连接" << std::endl;
            break;
        }
        std::cout << "收到来自客户端 " << client_ip << " 的消息:" << buffer << std::endl;
        std::string response = "服务器已收到消息:" + std::string(buffer);
        send(client_socket, response.c_str(), response.length(), 0);
        std::cout << "响应已发送给客户端 " << client_ip << std::endl;
        memset(buffer, 0, BUFFER_SIZE);
    }
    close(client_socket);
}

int main() {
    std::cout << "=== 多线程TCP服务器示例 ===" << std::endl;
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        std::cerr << "套接字创建失败" << std::endl;
        return 1;
    }
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        std::cerr << "设置套接字选项失败" << std::endl;
        close(server_fd);
        return 1;
    }
    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
        std::cerr << "绑定地址和端口失败" << std::endl;
        close(server_fd);
        return 1;
    }
    if (listen(server_fd, 3) < 0) {
        std::cerr << "监听连接失败" << std::endl;
        close(server_fd);
        return 1;
    }
    std::cout << "服务器正在监听端口 " << PORT << "..." << std::endl;
    int addrlen = sizeof(address);
    int new_socket;
    std::vector<std::thread> client_threads;
    while (true) {
        std::cout << "等待客户端连接..." << std::endl;
        new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            std::cerr << "接受连接失败" << std::endl;
            continue;
        }
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &address.sin_addr, client_ip, INET_ADDRSTRLEN);
        std::cout << "客户端 " << client_ip << " 已连接" << std::endl;
        client_threads.emplace_back(handleClient, new_socket, client_ip);
    }
    for (auto& thread : client_threads) {
        if (thread.joinable()) {
            thread.join();
        }
    }
    close(server_fd);
    return 0;
}

四、TCP客户端的实现

4.1 基本客户端结构
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>

const int PORT = 8080;
const int BUFFER_SIZE = 1024;
const std::string SERVER_IP = "127.0.0.1";

void receiveMessages(int sock) {
    char buffer[BUFFER_SIZE] = {0};
    while (true) {
        int valread = read(sock, buffer, BUFFER_SIZE);
        if (valread < 0) {
            std::cerr << "读取服务器响应失败" << std::endl;
            break;
        } else if (valread == 0) {
            std::cout << "服务器已断开连接" << std::endl;
            break;
        }
        std::cout << "服务器响应:" << buffer << std::endl;
        memset(buffer, 0, BUFFER_SIZE);
    }
}

int main() {
    std::cout << "=== TCP客户端示例 ===" << std::endl;
    // 1. 创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        std::cerr << "套接字创建失败" << std::endl;
        return 1;
    }
    // 2. 配置服务器地址
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP.c_str(), &serv_addr.sin_addr) <= 0) {
        std::cerr << "无效的服务器地址" << std::endl;
        close(sock);
        return 1;
    }
    // 3. 连接服务器
    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "连接服务器失败" << std::endl;
        close(sock);
        return 1;
    }
    std::cout << "已连接到服务器 " << SERVER_IP << ":" << PORT << std::endl;
    // 4. 接收服务器消息的线程
    std::thread recv_thread(receiveMessages, sock);
    recv_thread.detach();
    // 5. 发送消息
    std::string message;
    while (true) {
        std::cout << "请输入消息(输入\"quit\"退出): ";
        std::getline(std::cin, message);
        if (message == "quit") {
            break;
        }
        send(sock, message.c_str(), message.length(), 0);
    }
    // 6. 关闭套接字
    close(sock);
    return 0;
}

五、Boost.Asio库的使用

5.1 Boost.Asio基础

Boost.Asio是一个跨平台的网络编程库,它简化了网络编程的复杂流程,提供了异步、同步、单线程和多线程的编程模型。

5.2 使用Boost.Asio实现TCP服务器
#include <iostream>
#include <string>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
using namespace std;

const int PORT = 8080;

void handleClient(tcp::socket socket) {
    try {
        char buffer[1024];
        // 读取客户端消息
        size_t len = socket.read_some(boost::asio::buffer(buffer));
        string message(buffer, len);
        cout << "收到客户端消息:" << message << endl;
        // 发送响应
        string response = "服务器已收到消息:" + message;
        boost::asio::write(socket, boost::asio::buffer(response));
        cout << "响应已发送" << endl;
    } catch (const std::exception& e) {
        cerr << "处理客户端连接时出错:" << e.what() << endl;
    }
}

int main() {
    cout << "=== Boost.Asio TCP服务器示例 ===" << endl;
    try {
        boost::asio::io_service io_service;
        // 创建acceptor
        tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), PORT));
        cout << "服务器正在监听端口 " << PORT << "..." << endl;
        while (true) {
            // 接受连接
            tcp::socket socket(io_service);
            acceptor.accept(socket);
            // 处理连接
            thread t(handleClient, move(socket));
            t.detach();
        }
    } catch (const std::exception& e) {
        cerr << "服务器出错:" << e.what() << endl;
        return 1;
    }
    return 0;
}
5.3 使用Boost.Asio实现TCP客户端
#include <iostream>
#include <string>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
using namespace std;

const int PORT = 8080;
const string SERVER_IP = "127.0.0.1";

void receiveMessages(tcp::socket& socket) {
    try {
        char buffer[1024];
        while (true) {
            size_t len = socket.read_some(boost::asio::buffer(buffer));
            string response(buffer, len);
            cout << "服务器响应:" << response << endl;
        }
    } catch (const std::exception& e) {
        cerr << "读取服务器响应时出错:" << e.what() << endl;
    }
}

int main() {
    cout << "=== Boost.Asio TCP客户端示例 ===" << endl;
    try {
        boost::asio::io_service io_service;
        // 解析服务器地址
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(tcp::v4(), SERVER_IP, to_string(PORT));
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        // 连接服务器
        tcp::socket socket(io_service);
        boost::asio::connect(socket, endpoint_iterator);
        cout << "已连接到服务器 " << SERVER_IP << ":" << PORT << endl;
        // 接收服务器消息的线程
        thread t(receiveMessages, ref(socket));
        t.detach();
        // 发送消息
        string message;
        while (true) {
            cout << "请输入消息(输入\"quit\"退出): ";
            getline(cin, message);
            if (message == "quit") {
                break;
            }
            boost::asio::write(socket, boost::asio::buffer(message));
        }
    } catch (const std::exception& e) {
        cerr << "客户端出错:" << e.what() << endl;
        return 1;
    }
    return 0;
}

六、综合案例:实现一个简单的聊天服务器

6.1 项目结构
ChatServer/
├── include/
│   └── ChatServer.h
├── src/
│   ├── ChatServer.cpp
│   └── main.cpp
└── build/
6.2 核心代码
// include/ChatServer.h
#ifndef CHATSERVER_H
#define CHATSERVER_H
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
using namespace std;

class ChatServer {
private:
    boost::asio::io_service io_service;
    tcp::acceptor acceptor;
    vector<shared_ptr<tcp::socket>> clients;
    mutex clients_mutex;

    void acceptConnection();
    void handleClient(shared_ptr<tcp::socket> socket);
    void broadcastMessage(const string& message, const tcp::endpoint& sender_endpoint);

public:
    ChatServer(int port);
    void run();
};

#endif // CHATSERVER_H

// src/ChatServer.cpp
#include "ChatServer.h"

ChatServer::ChatServer(int port) : acceptor(io_service, tcp::endpoint(tcp::v4(), port)) {}

void ChatServer::run() {
    cout << "聊天服务器正在运行..." << endl;
    acceptConnection();
    io_service.run();
}

void ChatServer::acceptConnection() {
    shared_ptr<tcp::socket> socket = make_shared<tcp::socket>(io_service);
    acceptor.async_accept(*socket, [this, socket](const boost::system::error_code& ec) {
        if (!ec) {
            cout << "客户端 " << socket->remote_endpoint() << " 已连接" << endl;
            {
                lock_guard<mutex> lock(clients_mutex);
                clients.push_back(socket);
            }
            handleClient(socket);
        } else {
            cerr << "接受连接失败:" << ec.message() << endl;
        }
        acceptConnection();
    });
}

void ChatServer::handleClient(shared_ptr<tcp::socket> socket) {
    auto endpoint = socket->remote_endpoint();
    char buffer[1024];
    socket->async_read_some(boost::asio::buffer(buffer), [this, socket, endpoint](const boost::system::error_code& ec, size_t bytes_transferred) {
        if (!ec) {
            string message(buffer, bytes_transferred);
            cout << "收到来自 " << endpoint << " 的消息:" << message << endl;
            broadcastMessage(message, endpoint);
            handleClient(socket);
        } else {
            cout << "客户端 " << endpoint << " 已断开连接" << endl;
            {
                lock_guard<mutex> lock(clients_mutex);
                clients.erase(remove(clients.begin(), clients.end(), socket), clients.end());
            }
        }
    });
}

void ChatServer::broadcastMessage(const string& message, const tcp::endpoint& sender_endpoint) {
    string full_message = sender_endpoint.address().to_string() + ":" + to_string(sender_endpoint.port()) + " 说:" + message;
    {
        lock_guard<mutex> lock(clients_mutex);
        for (auto socket : clients) {
            if (socket->remote_endpoint() != sender_endpoint) {
                boost::asio::async_write(*socket, boost::asio::buffer(full_message), [](const boost::system::error_code& ec, size_t /*bytes_transferred*/) {
                    if (ec) {
                        cerr << "发送消息失败:" << ec.message() << endl;
                    }
                });
            }
        }
    }
}

// src/main.cpp
#include <iostream>
#include "ChatServer.h"

int main() {
    std::cout << "=== 简单的聊天服务器 ===" << std::endl;
    try {
        const int PORT = 8080;
        ChatServer server(PORT);
        server.run();
    } catch (const std::exception& e) {
        std::cerr << "服务器出错:" << e.what() << std::endl;
        return 1;
    }
    return 0;
}
6.3 项目构建与运行
# 创建构建目录
mkdir -p build && cd build
# 配置CMake
cmake -DCMAKE_BUILD_TYPE=Release ..
# 编译项目
cmake --build . --config Release
# 运行服务器
./ChatServer
# 在另一个终端运行客户端
./ChatClient

七、总结与练习

7.1 本章总结

本章介绍了C++网络编程的核心知识,包括:

  1. 网络编程的基本概念与TCP/IP协议
  2. 套接字编程基础
  3. TCP服务器的实现
  4. 多线程服务器的实现
  5. TCP客户端的实现
  6. Boost.Asio库的使用
  7. 综合案例:实现一个简单的聊天服务器
7.2 练习题
  1. 写一个程序,使用套接字编程实现一个简单的HTTP服务器。
  2. 编写一个函数,使用Boost.Asio库实现一个简单的FTP客户端。
  3. 写一个程序,使用多线程实现一个高并发的网络服务器。
  4. 实现一个类,使用Boost.Asio库实现一个简单的邮件服务器。
  5. 写一个程序,使用网络编程实现一个简单的实时数据传输系统。
7.3 进阶挑战
  1. 研究如何使用C++的无锁数据结构优化网络服务器的性能。
  2. 学习如何使用C++的协程(C++20及以后)与网络编程结合。
  3. 研究如何使用C++的并发编程优化一个大型网络应用。
  4. 学习如何使用C++的加密库(如OpenSSL)实现安全的网络通信。
  5. 研究如何使用C++的网络编程实现一个高可用性的分布式系统。

目录

  1. C++网络编程:TCP服务器与客户端实现
  2. 一、学习目标与重点
  3. 二、网络编程基础
  4. 2.1 TCP/IP协议简介
  5. 2.2 套接字编程基础
  6. 三、TCP服务器的实现
  7. 3.1 基本服务器结构
  8. 3.2 多线程服务器
  9. 四、TCP客户端的实现
  10. 4.1 基本客户端结构
  11. 五、Boost.Asio库的使用
  12. 5.1 Boost.Asio基础
  13. 5.2 使用Boost.Asio实现TCP服务器
  14. 5.3 使用Boost.Asio实现TCP客户端
  15. 六、综合案例:实现一个简单的聊天服务器
  16. 6.1 项目结构
  17. 6.2 核心代码
  18. 6.3 项目构建与运行
  19. 创建构建目录
  20. 配置CMake
  21. 编译项目
  22. 运行服务器
  23. 在另一个终端运行客户端
  24. 七、总结与练习
  25. 7.1 本章总结
  26. 7.2 练习题
  27. 7.3 进阶挑战

更多推荐文章

查看全部
  • 医疗送药机器人“空间拓扑优化+动态算法决策+多级容错控制”三重链式编程技术解析与应用
  • 智能协同云图库:Redis+Caffeine 多级缓存与图片全链路优化实战
  • 二叉树深度优先遍历实战:计算布尔值与路径数字和
  • 数据结构基础:顺序表详解与动态实现
  • 二分查找与双指针算法实战:LeetCode 704、35、34、27、977
  • 2026 年 AI 大模型实测排名与选型指南:国产模型表现亮眼
  • Java 电子招投标采购系统核心功能与业务流程设计
  • 人工智能:自然语言处理在医疗健康领域的应用与实战
  • 15 种高级 RAG 技术指南:从预检索到生成
  • 复杂三维山地环境下多无人机动态避障路径规划及小龙虾优化算法
  • Open-WebUI 管理员面板深度拆解与配置指南
  • AI 绘画参数调优指南:DeepFloyd IF 模型实战
  • 豆包 Seedream 4.0 多图融合实战:田园犬与三花猫的多场景生成测评
  • C++ 双指针算法:有效三角形个数与和为 S 的两个数字
  • 如何成为卓越的 AIGC 产品经理:从传统产品到 AI 领域的转型指南
  • Meta Llama 系列深度解析:开源大模型事实标准与架构演进
  • Spring Boot 抽奖模块设计:MQ 异步处理、缓存与状态管理
  • 前端请求后端返回 404/405/500 状态码排查与解决指南
  • 基于红黑树封装 C++ map/set:源码级实现与核心逻辑解析
  • PostgreSQL 无公网 IP 远程访问:基于 cpolar 内网穿透配置指南

相关免费在线工具

  • 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