@SEGA Project Sekai
4140 字
21 分钟
C++11 部分特性探讨
C++高级编程技术详解
1. 智能指针:shared_ptr
基本概念与用法
shared_ptr 是 C++11 引入的智能指针,采用引用计数机制自动管理动态分配的内存,有效防止内存泄漏和悬空指针问题。
#include <memory>#include <iostream>
int main() { // 创建 shared_ptr 的几种方式 std::shared_ptr<int> ptr1(new int(42)); // 直接初始化 std::shared_ptr<int> ptr2 = std::make_shared<int>(42); // 推荐方式,更高效 auto ptr3 = std::make_shared<int>(42); // 使用 auto 关键字
// 访问指针内容 std::cout << "Value: " << *ptr1 << std::endl; // 解引用 std::cout << "Address: " << ptr1.get() << std::endl; // 获取裸指针
// 检查是否唯一所有者 std::cout << "Use count: " << ptr1.use_count() << std::endl; std::cout << "Unique: " << ptr1.unique() << std::endl;
return 0;}引用计数机制详解
每个 shared_ptr 都会记录有多少个指针指向同一块内存,这个引用计数会随着指向该内存的 shared_ptr 数量的变化而动态调整:
#include <memory>#include <iostream>
void demonstrate_reference_counting() { auto ptr1 = std::make_shared<int>(100); std::cout << "After ptr1 creation - use_count: " << ptr1.use_count() << std::endl; // 1
{ auto ptr2 = ptr1; // 拷贝构造,引用计数+1 std::cout << "After ptr2 creation - use_count: " << ptr1.use_count() << std::endl; // 2
auto ptr3 = ptr1; // 引用计数再+1 std::cout << "After ptr3 creation - use_count: " << ptr1.use_count() << std::endl; // 3 } // ptr2 和 ptr3 离开作用域被销毁,引用计数-2
std::cout << "After ptr2, ptr3 destroyed - use_count: " << ptr1.use_count() << std::endl; // 1
ptr1.reset(); // 手动释放,引用计数归零,内存被释放 std::cout << "After reset - use_count: " << ptr1.use_count() << std::endl; // 0}自定义删除器
shared_ptr 支持自定义删除器,这在管理特殊资源时非常有用:
#include <memory>#include <iostream>
// 自定义删除器示例struct FileDeleter { void operator()(FILE* file) { if (file) { fclose(file); std::cout << "File closed successfully" << std::endl; } }};
void custom_deleter_example() { // 使用自定义删除器管理文件资源 std::shared_ptr<FILE> file_ptr(fopen("test.txt", "w"), FileDeleter()); if (file_ptr) { fputs("Hello, World!", file_ptr.get()); } // 文件会在 shared_ptr 销毁时自动关闭}
// Lambda 表达式作为删除器void lambda_deleter_example() { auto array_deleter = [](int* arr) { delete[] arr; std::cout << "Array deleted" << std::endl; };
std::shared_ptr<int> arr_ptr(new int[10], array_deleter);}循环引用问题及解决方案
shared_ptr 可能导致循环引用,需要使用 weak_ptr 来打破:
#include <memory>#include <iostream>
struct Node { std::string name; std::shared_ptr<Node> next; std::weak_ptr<Node> prev; // 使用 weak_ptr 避免循环引用
Node(const std::string& n) : name(n) { std::cout << "Node " << name << " created" << std::endl; }
~Node() { std::cout << "Node " << name << " destroyed" << std::endl; }};
void circular_reference_example() { auto node1 = std::make_shared<Node>("A"); auto node2 = std::make_shared<Node>("B");
node1->next = node2; node2->prev = node1; // 使用 weak_ptr,不会增加引用计数
std::cout << "node1 use_count: " << node1.use_count() << std::endl; // 1 std::cout << "node2 use_count: " << node2.use_count() << std::endl; // 2}2. 网络 I/O 编程
TCP 服务器完整实现
// Tcp Server:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <errno.h>
#define PORT 8080 // 服务器端口号(非特权端口,1024-65535)#define BACKLOG 10 // 最大等待连接队列长度#define BUFFER_SIZE 1024 // 数据缓冲区大小#define MAX_CLIENTS 100 // 最大客户端数量
// 全局变量,用于信号处理static volatile int keep_running = 1;
// 信号处理函数void signal_handler(int sig) { keep_running = 0; printf("\nReceived signal %d, shutting down...\n", sig);}
int main() { int server_fd, new_socket; struct sockaddr_in address; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0};
// 设置信号处理 signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler);
// 1. 创建 TCP 套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); }
// 设置 SO_REUSEADDR 选项,避免 TIME_WAIT 状态导致绑定失败 int opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { perror("setsockopt failed"); close(server_fd); exit(EXIT_FAILURE); }
// 2. 设置服务器地址结构 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT);
// 3. 绑定套接字 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); close(server_fd); exit(EXIT_FAILURE); }
// 4. 开始监听 if (listen(server_fd, BACKLOG) < 0) { perror("listen failed"); close(server_fd); exit(EXIT_FAILURE); }
printf("TCP Server started successfully, listening on port: %d\n", PORT); printf("Press Ctrl+C to stop the server\n");
// 5. 主服务器循环 while (keep_running) { // 使用 select 实现非阻塞检查,避免永久阻塞在 accept fd_set read_fds; FD_ZERO(&read_fds); FD_SET(server_fd, &read_fds);
struct timeval timeout; timeout.tv_sec = 1; // 1秒超时 timeout.tv_usec = 0;
int activity = select(server_fd + 1, &read_fds, NULL, NULL, &timeout);
if (activity < 0 && errno != EINTR) { perror("select error"); break; }
if (!keep_running) { break; // 收到停止信号 }
if (activity > 0 && FD_ISSET(server_fd, &read_fds)) { // 接受新连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept failed"); continue; }
// 打印客户端信息 printf("New client connected: %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
// 处理客户端请求 handle_client(new_socket, &address); } }
// 清理资源 printf("Server shutdown complete\n"); close(server_fd); return 0;}
// 客户端处理函数void handle_client(int client_socket, struct sockaddr_in* client_addr) { char buffer[BUFFER_SIZE]; char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client_addr->sin_addr), client_ip, INET_ADDRSTRLEN); int client_port = ntohs(client_addr->sin_port);
while (1) { memset(buffer, 0, BUFFER_SIZE); ssize_t bytes_read = read(client_socket, buffer, BUFFER_SIZE - 1);
if (bytes_read < 0) { perror("read failed"); break; } else if (bytes_read == 0) { printf("Client %s:%d disconnected\n", client_ip, client_port); break; }
// 处理接收到的数据 buffer[bytes_read] = '\0'; printf("Received from %s:%d: %s\n", client_ip, client_port, buffer);
// 简单的回声服务器逻辑 std::string response = "Echo: " + std::string(buffer); if (send(client_socket, response.c_str(), response.length(), 0) < 0) { perror("send failed"); break; }
// 检查退出命令 if (strncmp(buffer, "quit", 4) == 0) { printf("Client %s:%d requested disconnect\n", client_ip, client_port); break; } }
close(client_socket);}TCP 客户端实现
// TCP Client implementation#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <iostream>#include <string>
#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8080#define BUFFER_SIZE 1024
class TCPClient {private: int sockfd; struct sockaddr_in server_addr;
public: TCPClient() : sockfd(-1) { memset(&server_addr, 0, sizeof(server_addr)); }
bool connectToServer(const std::string& ip, int port) { // 创建套接字 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket creation failed"); return false; }
// 设置服务器地址 server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { perror("Invalid address"); close(sockfd); return false; }
// 连接服务器 if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("Connection failed"); close(sockfd); return false; }
std::cout << "Connected to server " << ip << ":" << port << std::endl; return true; }
void sendMessage(const std::string& message) { if (send(sockfd, message.c_str(), message.length(), 0) < 0) { perror("Send failed"); return; }
std::cout << "Sent: " << message << std::endl;
// 接收响应 char buffer[BUFFER_SIZE] = {0}; ssize_t bytes_received = read(sockfd, buffer, BUFFER_SIZE - 1); if (bytes_received > 0) { buffer[bytes_received] = '\0'; std::cout << "Received: " << buffer << std::endl; } }
void disconnect() { if (sockfd >= 0) { close(sockfd); sockfd = -1; std::cout << "Disconnected from server" << std::endl; } }
~TCPClient() { disconnect(); }};
// 使用示例int main() { TCPClient client;
if (client.connectToServer(SERVER_IP, SERVER_PORT)) { client.sendMessage("Hello, Server!"); client.sendMessage("How are you?"); client.sendMessage("quit"); // 退出命令 }
return 0;}程序执行流程深度解析
完整的程序启动和执行流程:
编译 → 链接 → 加载 → 运行时初始化 → main → 清理退出详细步骤:
- 编译阶段:源代码编译为目标文件
- 链接阶段:链接器将目标文件与库文件合并生成可执行文件
- 加载阶段:操作系统加载可执行文件到内存,创建进程
- 运行时初始化:
- 执行
_start入口点(由 CRT 提供) - 调用
__libc_start_main初始化 C 运行时环境 - 设置堆栈、初始化全局变量、解析命令行参数
- 执行
- main 函数执行:执行用户编写的代码
- 清理退出:
- 调用全局对象析构函数
- 执行
atexit注册的函数 - 调用
_exit系统调用终止进程
网络地址类型详解
| 类型 | 本质 | 访问范围 | 典型场景 | 使用示例 |
|---|---|---|---|---|
eth0: 192.168.243.123 | 具体接口的 IP | 仅限通过 eth0 接口的外部 / 内部访问 | 局域网内服务通信 | bind(server_fd, &addr, len) |
lo: 127.0.0.1 | 回环接口的本地 IP | 仅限本机内部访问 | 本地服务测试、进程间通信 | 本地测试、IPC |
any: 0.0.0.0 | 通配符地址(所有接口) | 所有接口的外部 / 内部访问 | 服务器监听所有网络(默认配置) | INADDR_ANY |
TCP 连接状态问题深度分析
TIME_WAIT 状态详解
产生原因: TIME_WAIT 是 TCP 四次挥手过程中的正常状态,确保网络中延迟的数据包能够被正确处理。
大量 TIME_WAIT 的解决方案:
// 1. 设置 SO_REUSEADDR 选项int reuse = 1;if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { perror("setsockopt SO_REUSEADDR failed");}
// 2. 使用连接池管理连接class ConnectionPool {private: std::queue<int> available_connections; std::unordered_set<int> all_connections; size_t max_pool_size;
public: ConnectionPool(size_t max_size) : max_pool_size(max_size) {}
int getConnection() { if (!available_connections.empty()) { int conn = available_connections.front(); available_connections.pop(); return conn; }
if (all_connections.size() < max_pool_size) { int new_conn = createNewConnection(); all_connections.insert(new_conn); return new_conn; }
return -1; // 连接池已满 }
void returnConnection(int conn) { available_connections.push(conn); }};
// 3. 调整系统参数(需要 root 权限)// 编辑 /etc/sysctl.conf:// net.ipv4.tcp_tw_reuse = 1// net.ipv4.tcp_tw_recycle = 1 # 注意:这个选项在现代内核中已被移除// net.ipv4.tcp_fin_timeout = 30 # 减少 FIN_WAIT2 超时时间CLOSE_WAIT 状态问题排查
根本原因:应用程序没有正确关闭连接。
排查和解决方法:
// 1. 确保所有路径都正确关闭连接void handle_client_robust(int client_socket) { // 使用 RAII 确保资源释放 class SocketGuard { private: int& sockfd; public: SocketGuard(int& sock) : sockfd(sock) {} ~SocketGuard() { if (sockfd >= 0) { close(sockfd); sockfd = -1; } } } guard(client_socket);
// 业务逻辑处理 process_client_request(client_socket); // guard 析构时会自动关闭 socket}
// 2. 添加超时机制#include <sys/select.h>
bool receive_with_timeout(int sockfd, char* buffer, size_t size, int timeout_sec) { fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sockfd, &read_fds);
struct timeval timeout; timeout.tv_sec = timeout_sec; timeout.tv_usec = 0;
int result = select(sockfd + 1, &read_fds, NULL, NULL, &timeout); if (result > 0 && FD_ISSET(sockfd, &read_fds)) { return read(sockfd, buffer, size) > 0; } return false;}
// 3. 使用状态机管理连接生命周期enum class ConnectionState { CONNECTED, READING, WRITING, CLOSING, CLOSED};
class Connection {private: int sockfd; ConnectionState state; time_t last_activity;
public: void check_timeout() { time_t now = time(nullptr); if (now - last_activity > 30) { // 30秒超时 close_connection(); } }
void close_connection() { if (state != ConnectionState::CLOSED) { shutdown(sockfd, SHUT_RDWR); close(sockfd); state = ConnectionState::CLOSED; } }};3. C++20 协程
协程基础概念
协程 vs 普通函数:
| 特性 | 普通函数 | 协程 |
|---|---|---|
| 执行流程 | 一次性执行完成 | 可暂停和恢复 |
| 状态保存 | 不保存局部变量状态 | 保存完整的执行状态 |
| 调用关系 | 调用者等待被调用者完成 | 调用者和被调用者可交替执行 |
| 适用场景 | 简单同步逻辑 | 异步I/O、生成器、状态机 |
完整的协程框架实现
#include <coroutine>#include <iostream>#include <memory>#include <thread>#include <chrono>#include <vector>
// 1. 简单的任务协程struct SimpleTask { struct promise_type { SimpleTask get_return_object() { return SimpleTask{ std::coroutine_handle<promise_type>::from_promise(*this) }; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } };
std::coroutine_handle<promise_type> handle;
explicit SimpleTask(std::coroutine_handle<promise_type> h) : handle(h) {} ~SimpleTask() { if (handle) handle.destroy(); }
void resume() { if (handle && !handle.done()) handle.resume(); } bool done() const { return handle.done(); }};
// 2. 带值的任务协程template<typename T>struct ValueTask { struct promise_type { T value;
ValueTask get_return_object() { return ValueTask{ std::coroutine_handle<promise_type>::from_promise(*this) }; } std::suspend_never initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_value(T val) { value = std::move(val); } void unhandled_exception() { std::terminate(); }
// 支持 co_yield std::suspend_always yield_value(T val) { value = std::move(val); return {}; } };
std::coroutine_handle<promise_type> handle;
explicit ValueTask(std::coroutine_handle<promise_type> h) : handle(h) {} ~ValueTask() { if (handle) handle.destroy(); }
T get_value() const { return handle.promise().value; } void resume() { if (!handle.done()) handle.resume(); } bool done() const { return handle.done(); }};
// 3. 异步操作等待器struct AsyncOperation { bool completed{false}; std::function<void()> completion_handler;
bool await_ready() const { return completed; }
void await_suspend(std::coroutine_handle<> handle) { // 模拟异步操作 std::thread([this, handle]() mutable { std::this_thread::sleep_for(std::chrono::milliseconds(100)); completed = true; if (completion_handler) completion_handler(); handle.resume(); // 恢复协程 }).detach(); }
void await_resume() { std::cout << "Async operation completed!" << std::endl; }};
// 4. 高级生成器实现template<typename T>class Generator {public: struct promise_type { T current_value; std::exception_ptr exception;
Generator get_return_object() { return Generator{ std::coroutine_handle<promise_type>::from_promise(*this) }; }
std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(T value) { current_value = std::move(value); return {}; }
void return_void() {} void unhandled_exception() { exception = std::current_exception(); } };
using handle_type = std::coroutine_handle<promise_type>;
explicit Generator(handle_type h) : coro(h) {} ~Generator() { if (coro) coro.destroy(); }
// 禁用拷贝 Generator(const Generator&) = delete; Generator& operator=(const Generator&) = delete;
// 允许移动 Generator(Generator&& other) noexcept : coro(other.coro) { other.coro = {}; }
Generator& operator=(Generator&& other) noexcept { if (this != &other) { if (coro) coro.destroy(); coro = other.coro; other.coro = {}; } return *this; }
// 迭代器支持 class iterator { public: explicit iterator(handle_type coro = {}) : coro(coro) {}
iterator& operator++() { if (coro && !coro.done()) { coro.resume(); } return *this; }
bool operator==(const iterator& other) const { return coro == other.coro || (coro.done() && other.coro.done()); }
bool operator!=(const iterator& other) const { return !(*this == other); }
const T& operator*() const { return coro.promise().current_value; }
const T* operator->() const { return &coro.promise().current_value; }
private: handle_type coro; };
iterator begin() { if (coro && !coro.done()) { coro.resume(); } return iterator{coro}; }
iterator end() { return iterator{}; }
private: handle_type coro;};协程使用示例
// 1. 生成器使用示例Generator<int> fibonacci(int limit) { int a = 0, b = 1; for (int i = 0; i < limit; ++i) { co_yield a; std::tie(a, b) = std::make_pair(b, a + b); }}
Generator<std::string> tokenize(const std::string& text, char delimiter) { size_t start = 0, end = 0; while ((end = text.find(delimiter, start)) != std::string::npos) { co_yield text.substr(start, end - start); start = end + 1; } co_yield text.substr(start);}
// 2. 异步任务使用示例ValueTask<int> async_multiply(int a, int b) { std::cout << "Starting async multiplication..." << std::endl;
// 模拟异步操作 co_await AsyncOperation{};
int result = a * b; std::cout << "Multiplication completed: " << a << " * " << b << " = " << result << std::endl;
co_return result;}
SimpleTask run_async_operations() { std::cout << "Starting multiple async operations..." << std::endl;
auto task1 = async_multiply(6, 7); auto task2 = async_multiply(8, 9);
// 等待任务完成 while (!task1.done() || !task2.done()) { if (!task1.done()) task1.resume(); if (!task2.done()) task2.resume(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
std::cout << "All operations completed!" << std::endl; std::cout << "Results: " << task1.get_value() << ", " << task2.get_value() << std::endl;}
// 3. 网络I/O协程示例(概念性)struct AsyncReadOperation { int socket_fd; char* buffer; size_t size;
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> handle) { // 在实际实现中,这里会使用 epoll/kqueue/IOCP 等异步I/O机制 std::thread([this, handle]() mutable { ssize_t bytes_read = read(socket_fd, buffer, size); if (bytes_read >= 0) { handle.resume(); } // 错误处理... }).detach(); }
ssize_t await_resume() { // 返回实际读取的字节数 return 0; // 简化实现 }};
// 主函数演示int main() { std::cout << "=== Generator Examples ===" << std::endl;
// 斐波那契数列生成器 std::cout << "Fibonacci sequence: "; for (auto num : fibonacci(10)) { std::cout << num << " "; } std::cout << std::endl;
// 字符串分割生成器 std::cout << "Tokenized string: "; for (const auto& token : tokenize("hello,world,how,are,you", ',')) { std::cout << "[" << token << "] "; } std::cout << std::endl;
std::cout << "\n=== Async Task Examples ===" << std::endl; run_async_operations();
return 0;}协程性能优化技巧
// 1. 协程内存池class CoroutineMemoryPool {private: std::vector<std::unique_ptr<char[]>> memory_blocks; size_t block_size;
public: CoroutineMemoryPool(size_t size = 4096) : block_size(size) {}
void* allocate(size_t size) { if (size <= block_size && !memory_blocks.empty()) { auto block = std::move(memory_blocks.back()); memory_blocks.pop_back(); return block.release(); } return ::operator new(size); }
void deallocate(void* ptr, size_t size) { if (size <= block_size) { memory_blocks.push_back(std::unique_ptr<char[]>(static_cast<char*>(ptr))); } else { ::operator delete(ptr); } }};
// 2. 自定义协程内存分配器template<typename Promise>struct custom_coroutine_traits { static CoroutineMemoryPool pool;
static void* operator new(size_t size) { return pool.allocate(size); }
static void operator delete(void* ptr, size_t size) { pool.deallocate(ptr, size); }};
// 3. 批量协程调度class CoroutineScheduler {private: std::vector<std::coroutine_handle<>> ready_coroutines; std::vector<std::coroutine_handle<>> suspended_coroutines;
public: void schedule(std::coroutine_handle<> coro) { ready_coroutines.push_back(coro); }
void run_batch(size_t max_executions = 1000) { for (size_t i = 0; i < max_executions && !ready_coroutines.empty(); ++i) { auto coro = ready_coroutines.back(); ready_coroutines.pop_back();
if (!coro.done()) { coro.resume(); if (!coro.done()) { suspended_coroutines.push_back(coro); } } }
// 交换准备就绪的协程 std::swap(ready_coroutines, suspended_coroutines); suspended_coroutines.clear(); }};协程最佳实践和陷阱
最佳实践:
- 使用 RAII 管理协程句柄
- 避免在协程中持有大量堆栈数据
- 使用生成器处理大数据序列
- 合理设置协程调度策略
常见陷阱:
// 错误示例:悬空引用Generator<int&> bad_generator() { int value = 42; co_yield value; // 错误:返回局部变量的引用} // value 被销毁,引用悬空
// 正确做法:返回值或使用智能指针Generator<std::unique_ptr<int>> good_generator() { auto value = std::make_unique<int>(42); co_yield std::move(value);}
// 错误示例:忘记检查协程状态void unsafe_coroutine_use() { auto coro = some_coroutine(); coro.resume(); // 可能访问已销毁的协程}
// 正确做法:使用 RAII 和状态检查class SafeCoroutineWrapper { std::coroutine_handle<> handle; bool valid{false};
public: template<typename Coroutine> SafeCoroutineWrapper(Coroutine&& coro) : handle(coro.handle), valid(true) {}
~SafeCoroutineWrapper() { if (valid && handle) { handle.destroy(); } }
bool resume() { if (valid && handle && !handle.done()) { handle.resume(); return true; } return false; }
// 禁用拷贝,允许移动 SafeCoroutineWrapper(const SafeCoroutineWrapper&) = delete; SafeCoroutineWrapper& operator=(const SafeCoroutineWrapper&) = delete; SafeCoroutineWrapper(SafeCoroutineWrapper&& other) noexcept : handle(other.handle), valid(other.valid) { other.valid = false; }};4. 综合应用:基于协程的网络服务器
#include <coroutine>#include <iostream>#include <memory>#include <vector>#include <unordered_map>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>
// 基于协程的异步TCP服务器class AsyncTCPServer {private: int server_fd; std::unordered_map<int, std::coroutine_handle<>> client_coroutines;
public: AsyncTCPServer(int port) { server_fd = socket(AF_INET, SOCK_STREAM, 0);
// 设置非阻塞 fcntl(server_fd, F_SETFL, O_NONBLOCK);
sockaddr_in server_addr{}; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port);
bind(server_fd, (sockaddr*)&server_addr, sizeof(server_addr)); listen(server_fd, 10); }
~AsyncTCPServer() { for (auto& [fd, coro] : client_coroutines) { if (coro) coro.destroy(); close(fd); } close(server_fd); }
// 接受连接的协程 struct AcceptOperation { AsyncTCPServer& server; int client_fd{-1};
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> handle) { // 在实际实现中,这里会注册到epoll等事件循环 std::thread([this, handle]() mutable { sockaddr_in client_addr{}; socklen_t addr_len = sizeof(client_addr);
while ((client_fd = accept(server.server_fd, (sockaddr*)&client_addr, &addr_len)) < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
if (client_fd >= 0) { fcntl(client_fd, F_SETFL, O_NONBLOCK); handle.resume(); } }).detach(); }
int await_resume() { return client_fd; } };
AcceptOperation async_accept() { return AcceptOperation{*this}; }
// 处理客户端连接的协程任务 SimpleTask handle_client(int client_fd) { char buffer[1024];
while (true) { // 模拟异步读取 co_await AsyncOperation{};
ssize_t bytes_read = read(client_fd, buffer, sizeof(buffer) - 1); if (bytes_read <= 0) { break; }
buffer[bytes_read] = '\0'; std::cout << "Received: " << buffer << std::endl;
// 回声响应 write(client_fd, buffer, bytes_read); }
close(client_fd); client_coroutines.erase(client_fd); }
// 启动服务器 SimpleTask start() { std::cout << "Async TCP Server started" << std::endl;
while (true) { int client_fd = co_await async_accept(); if (client_fd >= 0) { std::cout << "New client connected: " << client_fd << std::endl; auto task = handle_client(client_fd); client_coroutines[client_fd] = task.handle; } } }};
// 使用示例int main() { AsyncTCPServer server(8080);
// 在实际应用中,这里会有事件循环来驱动协程 auto main_task = server.start();
// 简单的事件循环模拟 while (true) { std::this_thread::sleep_for(std::chrono::seconds(1)); }
return 0;}这个完整的指南涵盖了现代 C++ 编程中的三个重要主题:智能指针、网络编程和协程。每个主题都包含了从基础到高级的详细说明、实际代码示例和最佳实践建议,可以帮助开发者深入理解这些概念并在实际项目中应用它们。
C++11 部分特性探讨
https://mizuki.mysqil.com/posts/20251027_1/20251027/ 部分信息可能已经过时