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

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>constint PORT =8080;constint BUFFER_SIZE =1024;intmain(){ std::cout <<"=== TCP服务器示例 ==="<< std::endl;// 1. 创建套接字int server_fd =socket(AF_INET, SOCK_STREAM,0);if(server_fd <0){ std::cerr <<"套接字创建失败"<< std::endl;return1;}// 2. 设置套接字选项,允许地址复用int opt =1;if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,&opt,sizeof(opt))<0){ std::cerr <<"设置套接字选项失败"<< std::endl;close(server_fd);return1;}// 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,(structsockaddr*)&address,sizeof(address))<0){ std::cerr <<"绑定地址和端口失败"<< std::endl;close(server_fd);return1;}// 4. 监听连接if(listen(server_fd,3)<0){ std::cerr <<"监听连接失败"<< std::endl;close(server_fd);return1;} std::cout <<"服务器正在监听端口 "<< PORT <<"..."<< std::endl;// 5. 接受连接int addrlen =sizeof(address);int new_socket;while(true){ std::cout <<"等待客户端连接..."<< std::endl; new_socket =accept(server_fd,(structsockaddr*)&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);return0;}

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>constint PORT =8080;constint BUFFER_SIZE =1024;voidhandleClient(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;}elseif(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);}intmain(){ std::cout <<"=== 多线程TCP服务器示例 ==="<< std::endl;int server_fd =socket(AF_INET, SOCK_STREAM,0);if(server_fd <0){ std::cerr <<"套接字创建失败"<< std::endl;return1;}int opt =1;if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,&opt,sizeof(opt))<0){ std::cerr <<"设置套接字选项失败"<< std::endl;close(server_fd);return1;} sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port =htons(PORT);if(bind(server_fd,(structsockaddr*)&address,sizeof(address))<0){ std::cerr <<"绑定地址和端口失败"<< std::endl;close(server_fd);return1;}if(listen(server_fd,3)<0){ std::cerr <<"监听连接失败"<< std::endl;close(server_fd);return1;} 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,(structsockaddr*)&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);return0;}

四、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>constint PORT =8080;constint BUFFER_SIZE =1024;const std::string SERVER_IP ="127.0.0.1";voidreceiveMessages(int sock){char buffer[BUFFER_SIZE]={0};while(true){int valread =read(sock, buffer, BUFFER_SIZE);if(valread <0){ std::cerr <<"读取服务器响应失败"<< std::endl;break;}elseif(valread ==0){ std::cout <<"服务器已断开连接"<< std::endl;break;} std::cout <<"服务器响应: "<< buffer << std::endl;memset(buffer,0, BUFFER_SIZE);}}intmain(){ std::cout <<"=== TCP客户端示例 ==="<< std::endl;// 1. 创建套接字int sock =socket(AF_INET, SOCK_STREAM,0);if(sock <0){ std::cerr <<"套接字创建失败"<< std::endl;return1;}// 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);return1;}// 3. 连接服务器if(connect(sock,(structsockaddr*)&serv_addr,sizeof(serv_addr))<0){ std::cerr <<"连接服务器失败"<< std::endl;close(sock);return1;} 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);return0;}

五、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;usingnamespace std;constint PORT =8080;voidhandleClient(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;}}intmain(){ 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;return1;}return0;}

5.3 使用Boost.Asio实现TCP客户端

#include<iostream>#include<string>#include<boost/asio.hpp>using boost::asio::ip::tcp;usingnamespace std;constint PORT =8080;const string SERVER_IP ="127.0.0.1";voidreceiveMessages(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;}}intmain(){ 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;return1;}return0;}

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

6.1 项目结构

ChatServer/ ├── include/ │ └── ChatServer.h ├── src/ │ ├── ChatServer.cpp │ └── main.cpp └── build/ 

6.2 核心代码

// include/ChatServer.h#ifndefCHATSERVER_H#defineCHATSERVER_H#include<iostream>#include<string>#include<vector>#include<thread>#include<mutex>#include<boost/asio.hpp>using boost::asio::ip::tcp;usingnamespace std;classChatServer{private: boost::asio::io_service io_service; tcp::acceptor acceptor; vector<shared_ptr<tcp::socket>> clients; mutex clients_mutex;voidacceptConnection();voidhandleClient(shared_ptr<tcp::socket> socket);voidbroadcastMessage(const string& message,const tcp::endpoint& sender_endpoint);public:ChatServer(int port);voidrun();};#endif// CHATSERVER_H// src/ChatServer.cpp#include"ChatServer.h"ChatServer::ChatServer(int port):acceptor(io_service, tcp::endpoint(tcp::v4(), port)){}voidChatServer::run(){ cout <<"聊天服务器正在运行..."<< endl;acceptConnection(); io_service.run();}voidChatServer::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();});}voidChatServer::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());}}});}voidChatServer::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"intmain(){ std::cout <<"=== 简单的聊天服务器 ==="<< std::endl;try{constint PORT =8080; ChatServer server(PORT); server.run();}catch(const std::exception& e){ std::cerr <<"服务器出错: "<< e.what()<< std::endl;return1;}return0;}

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++的网络编程实现一个高可用性的分布式系统。

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk