当前位置: 首页 > news >正文

使用C++11的`std::future`和`std::promise`实现异步网络通信

使用C++11的std::futurestd::promise实现异步网络通信

在现代C++编程中,异步编程是一个重要的主题。C++11引入了std::futurestd::promise,为异步编程提供了强大的工具。本文将详细介绍如何使用std::futurestd::promise实现异步网络通信,并提供丰富的示例代码。

什么是std::futurestd::promise

std::futurestd::promise是C++11标准库中的两个类,用于实现异步操作:

  • std::promise:用于设置一个值或异常,该值或异常可以在另一个线程中被获取。
  • std::future:用于获取由std::promise设置的值或异常。

通过std::promisestd::future,我们可以在一个线程中启动一个异步操作,并在另一个线程中等待其完成。

实现异步网络通信的步骤
  1. 创建Socket:使用socket函数创建一个Socket。
  2. 连接服务器:使用connect函数连接到服务器。
  3. 发送和接收消息:使用sendrecv函数进行消息传递。
  4. 使用std::promisestd::future:在异步操作中使用std::promisestd::future来实现异步通信。
示例代码

以下是实现一个简单的异步TCP客户端的完整代码示例:

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <future>const int PORT = 8080;
const int BUFFER_SIZE = 1024;std::string async_send_receive(const std::string& server_ip, const std::string& message) {// 创建Socketint client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {throw std::runtime_error("Failed to create socket");}// 服务器地址sockaddr_in server_addr;std::memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr);// 连接服务器if (connect(client_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {close(client_socket);throw std::runtime_error("Failed to connect to server");}// 发送消息send(client_socket, message.c_str(), message.size(), 0);// 接收响应char buffer[BUFFER_SIZE];std::memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);if (bytes_received < 0) {close(client_socket);throw std::runtime_error("Failed to receive response");}// 关闭连接close(client_socket);return std::string(buffer, bytes_received);
}int main() {std::string server_ip = "127.0.0.1";std::string message = "Hello, Server!";// 创建promise和futurestd::promise<std::string> promise;std::future<std::string> future = promise.get_future();// 启动异步任务std::thread([&promise, &server_ip, &message]() {try {std::string response = async_send_receive(server_ip, message);promise.set_value(response);} catch (const std::exception& e) {promise.set_exception(std::current_exception());}}).detach();// 等待并获取结果try {std::string response = future.get();std::cout << "Received response: " << response << std::endl;} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;}return 0;
}
代码解析
  1. 创建Socket

    int client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket == -1) {throw std::runtime_error("Failed to create socket");
    }
    

    这行代码创建了一个TCP Socket。AF_INET表示使用IPv4地址,SOCK_STREAM表示使用TCP协议。

  2. 连接服务器

    sockaddr_in server_addr;
    std::memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr);if (connect(client_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {close(client_socket);throw std::runtime_error("Failed to connect to server");
    }
    

    这段代码将客户端连接到指定的服务器地址和端口。

  3. 发送和接收消息

    send(client_socket, message.c_str(), message.size(), 0);char buffer[BUFFER_SIZE];
    std::memset(buffer, 0, BUFFER_SIZE);
    int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);
    if (bytes_received < 0) {close(client_socket);throw std::runtime_error("Failed to receive response");
    }close(client_socket);return std::string(buffer, bytes_received);
    

    这段代码发送消息给服务器,然后等待接收服务器的响应。接收到响应后,关闭连接并返回响应内容。

  4. 使用std::promisestd::future

    std::promise<std::string> promise;
    std::future<std::string> future = promise.get_future();std::thread([&promise, &server_ip, &message]() {try {std::string response = async_send_receive(server_ip, message);promise.set_value(response);} catch (const std::exception& e) {promise.set_exception(std::current_exception());}
    }).detach();try {std::string response = future.get();std::cout << "Received response: " << response << std::endl;
    } catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;
    }
    

    这段代码创建了一个std::promise对象,并通过get_future方法获取对应的std::future对象。然后启动一个新线程,在新线程中执行异步任务,并将结果设置到std::promise中。主线程等待std::future获取结果,并处理异常。

进一步优化

虽然上述代码实现了一个基本的异步TCP客户端,但在实际应用中,我们可能需要进一步优化和扩展功能:

  1. 错误处理:添加更多的错误处理逻辑,处理各种可能的网络错误。
  2. 超时机制:实现超时机制,避免异步操作无限期等待。
  3. 多线程处理:使用线程池或异步I/O来提高并发性能。
  4. 数据序列化:使用数据序列化技术(如JSON或Protobuf)来传输复杂的数据结构。
超时机制示例

以下是一个实现超时机制的示例:

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <future>
#include <chrono>const int PORT = 8080;
const int BUFFER_SIZE = 1024;std::string async_send_receive(const std::string& server_ip, const std::string& message) {// 创建Socketint client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {throw std::runtime_error("Failed to create socket");}// 服务器地址sockaddr_in server_addr;std::memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr);// 连接服务器if (connect(client_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {close(client_socket);throw std::runtime_error("Failed to connect to server");}// 发送消息send(client_socket, message.c_str(), message.size(), 0);// 接收响应char buffer[BUFFER_SIZE];std::memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);if (bytes_received < 0) {close(client_socket);throw std::runtime_error("Failed to receive response");}// 关闭连接close(client_socket);return std::string(buffer, bytes_received);
}int main() {std::string server_ip = "127.好的,我们继续。#### 超时机制示例(续)以下是一个实现超时机制的完整示例:```cpp
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <future>
#include <chrono>const int PORT = 8080;
const int BUFFER_SIZE = 1024;std::string async_send_receive(const std::string& server_ip, const std::string& message) {// 创建Socketint client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {throw std::runtime_error("Failed to create socket");}// 服务器地址sockaddr_in server_addr;std::memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr);// 连接服务器if (connect(client_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {close(client_socket);throw std::runtime_error("Failed to connect to server");}// 发送消息send(client_socket, message.c_str(), message.size(), 0);// 接收响应char buffer[BUFFER_SIZE];std::memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);if (bytes_received < 0) {close(client_socket);throw std::runtime_error("Failed to receive response");}// 关闭连接close(client_socket);return std::string(buffer, bytes_received);
}int main() {std::string server_ip = "127.0.0.1";std::string message = "Hello, Server!";// 创建promise和futurestd::promise<std::string> promise;std::future<std::string> future = promise.get_future();// 启动异步任务std::thread([&promise, &server_ip, &message]() {try {std::string response = async_send_receive(server_ip, message);promise.set_value(response);} catch (const std::exception& e) {promise.set_exception(std::current_exception());}}).detach();// 等待并获取结果,设置超时时间为5秒if (future.wait_for(std::chrono::seconds(5)) == std::future_status::ready) {try {std::string response = future.get();std::cout << "Received response: " << response << std::endl;} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;}} else {std::cerr << "Request timed out" << std::endl;}return 0;
}

在这个示例中,我们使用std::future::wait_for方法设置了一个超时时间为5秒。如果在5秒内没有收到响应,程序将输出“Request timed out”。

总结

通过本文,我们详细介绍了如何使用C++11的std::futurestd::promise实现异步网络通信。我们探讨了std::futurestd::promise的基本概念、实现异步TCP客户端的具体步骤和代码,并展示了如何实现超时机制。

理解和掌握这些技术可以帮助你在异步编程和网络编程领域取得更大的进步。希望这篇文章能帮助你更好地理解和应用std::futurestd::promise。如果你有任何问题或需要进一步的帮助,请随时联系我。Happy coding!

相关文章:

使用C++11的`std::future`和`std::promise`实现异步网络通信

使用C11的std::future和std::promise实现异步网络通信 在现代C编程中&#xff0c;异步编程是一个重要的主题。C11引入了std::future和std::promise&#xff0c;为异步编程提供了强大的工具。本文将详细介绍如何使用std::future和std::promise实现异步网络通信&#xff0c;并提…...

【C++登堂入室】类与对象(上)

目录 一、面向过程和面向对象初步认识 二、类的引入 三、类的定义 四、类的访问限定符及封装 4.1 访问限定符 4.2 封装 五、类的作用域 六、类的实例化 七、类对象模型 7.1如何计算类对象的大小 7.2 类对象的存储方式猜测 7.3 结构体内存对齐规则 八、this指针 …...

【西电电装实习】5. 无人机模块及作用、上位机的操作

文章目录 前言一、硬件结构电源、电源电压测试电路晶振外围陀螺仪信号放大电路及天线空心杯&#xff08;电极&#xff09;驱动电路 软件设置整机装配PID 参数设置公式 参考文献 前言 西电电装实习&#xff0c;无人机原理图、上位机的调节方法 一、硬件结构 电源、电源电压测试…...

有关WSL和docker的介绍

目录标题 如何利用在windows上配置docker实现linux和windows容器修改WSL默认安装&#xff08;也就是linux子系统&#xff09;目录到其他盘 如何利用在windows上配置docker实现linux和windows容器 wsl的基本命令&#xff1a;参考网页 docker入门到实践&#xff1a;参考网页 官方…...

以太坊入门

1. 以太坊简介 Vitalik Buterin 在 2013 年 11 月提出了以太坊的概念&#xff0c;其关键思想是&#xff1a;开发一种图灵完备&#xff08;Turing-Complete) 的语言&#xff0c;以允许开发用于区块链和去中心化应用的任意程序&#xff08;智能合约&#xff09;。该概念与比特比相…...

秃姐学AI系列之:实战Kaggle比赛:狗的品种识别(ImageNet Dogs)

目录 前置准备 整理数据集 图片增广 读取数据集 微调预训练模型 训练函数 训练和验证模型 Kaggle提交结果 前置准备 常规导包 import os import torch import torchvision from torch import nn from d2l import torch as d2l 使用小规模数据样本 d2l.DATA_HUB[dog…...

图神经网络介绍3

1. 图同构网络&#xff1a;Weisfeiler-Lehman 测试与图神经网络的表达力 本节介绍一个关于图神经网络表达力的经典工作&#xff0c;以及随之产生的另一个重要的模型——图同构网络。图同构问题指的是验证两个图在拓扑结构上是否相同。Weisfeiler-Lehman 测试是一种有效的检验两…...

浅谈 React Fiber

想象一下&#xff0c;你正在搭建一个乐高积木城堡。 传统的搭建方式&#xff1a;一次性把所有积木拼好&#xff0c;如果中途发现某个地方拼错了&#xff0c;就需要拆掉重新拼。这个过程就像 React 15 之前的版本&#xff0c;一旦开始渲染&#xff0c;就很难中断&#xff0c;效…...

Winform实现石头剪刀布小游戏

1、电脑玩家类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace RockScissorsClothApp {public class Computer{public Card Play(){Random random new Random();int num random.Next(0, 3…...

计算机的错误计算(九十)

摘要 计算机的错误计算&#xff08;八十九&#xff09;探讨了反双曲余切函数 acoth(x)在 附近的计算精度问题。本节讨论绝对值为大数的反双曲余切函数值的计算精度问题。 Acoth(x) 函数的定义为&#xff1a; 其中 x 的绝对值大于 1 . 例1. 计算 acoth(1.000000000002e15) .…...

对游戏语音软件Oopz遭遇DDoS攻击后的一些建议

由于武汉天气太热&#xff0c;因此周末两天就没怎么出门。一直在家打《黑神话&#xff1a;悟空》&#xff0c;结果卡在广智这里一直打不过去&#xff0c;本来想找好友一起讨论下该怎么过&#xff0c;但又没有好的游戏语音软件。于是在网上搜索了一些信息&#xff0c;并偶然间发…...

解锁Android开发利器:MVVM架构_android的mvvm

// 从网络或其他数据源获取天气数据return Weather(city, "25C") }} 2.定义View&#xff1a;class WeatherActivity : AppCompatActivity() { private lateinit var viewModel: WeatherViewModel override fun onCreate(savedInstanceState: Bundle?) {super.onCre…...

llama.cpp demo

git clone https://github.com/ggerganov/llama.cpp cd llama.cpp 修改Makefile使能mfma参数 MK_CFLAGS -mfma -mf16c -mavx MK_CXXFLAGS -mfma -mf16c -mavx 安装python3依赖 cat ./requirements/requirements-convert_legacy_llama.txt numpy~1.26.4 sentencepie…...

OpenCV结构分析与形状描述符(19)查找二维点集的最小面积外接旋转矩形函数minAreaRect()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 找到一个包围输入的二维点集的最小面积旋转矩形。 该函数计算并返回指定点集的最小面积边界矩形&#xff08;可能是旋转的&#xff09;。开发者…...

[SWPU2019]Web1 超详细教程

老规矩先看源码&#xff0c;没找到啥提示&#xff0c;后面就是登录口对抗 弱口令试了几个不行&#xff0c;就注册了个账户登录进去 可以发布广告&#xff0c;能造成xss&#xff0c;但是没啥用啊感觉 查看广告信息的时候&#xff0c;注意到url当中存在id参数&#xff0c;可能存…...

【区块链通用服务平台及组件】基于向量数据库与 LLM 的智能合约 Copilot

智能合约是自动执行、无需信任的代码&#xff0c;可以在区块链上运行&#xff0c;确保了数据和程序的透明性和不可篡改性。然而&#xff0c; 智能合约的编写、调试和优化仍然是一个具有挑战性的过程&#xff0c;因为它需要高度的技术专长&#xff0c;且发布后的智能合约代码通常…...

mfc140u.dll丢失有啥方法能够进行修复?分享几种mfc140u.dll丢失的解决办法

你是否曾遇到过这样的情况&#xff1a;当你满怀期待地打开一个应用程序时&#xff0c;却被一个错误提示拦住了去路&#xff0c;提示信息中指出 mfc140u.dll 文件丢失。这个问题可能会让你感到困惑和无助&#xff0c;但是不要担心&#xff0c;本文将为你详细解读 mfc140u.dll 丢…...

【PyQt6 应用程序】在用户登录界面实现密码密文保存复用

在开发现代应用程序中,为用户提供既安全又便捷的登录体验是至关重要的。特别是在那些需要用户认证的应用中,实现一个功能丰富且用户友好的登录界面不仅能增强用户满意度,还能提升整体的安全性。基于PyQt6框架和QtDesigner,本文将展示如何在已有的用户登录页面基础上,进一步…...

赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践

赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践 AI 语音交互大模型其实有两种主流的做法: All in LLM多个模块组合, ASR+LLM+TTS实际应用中,这两种方案并不是要对立存在的,像永劫无间这种游戏的场景,用户要的是低延迟,无障碍交流。并且能够触发某些动作技…...

游戏论坛网站|基于Springboot+vue的游戏论坛网站系统游戏分享网站(源码+数据库+文档)

游戏论坛|游戏论坛系统|游戏分享网站 目录 基于Springbootvue的游戏论坛网站系统游戏分享网站 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大…...

【go】pprof 性能分析

前言 go pprof是 Go 语言提供的性能分析工具。它可以帮助开发者分析 Go 程序的性能问题&#xff0c;包括 CPU 使用情况、内存分配情况、阻塞情况等。 主要功能 CPU 性能分析 go pprof可以对程序的 CPU 使用情况进行分析。它通过在一定时间内对程序的执行进行采样&#xff0…...

Python | Leetcode Python题解之第397题整数替换

题目&#xff1a; 题解&#xff1a; class Solution:def integerReplacement(self, n: int) -> int:ans 0while n ! 1:if n % 2 0:ans 1n // 2elif n % 4 1:ans 2n // 2else:if n 3:ans 2n 1else:ans 2n n // 2 1return ans...

JDBC使用

7.2 创建JDBC应用 7.2.1 创建JDBC应用程序的步骤 使用JDBC操作数据库中的数据包括6个基本操作步骤&#xff1a; &#xff08;1&#xff09;载入JDBC驱动程序&#xff1a; 首先要在应用程序中加载驱动程序driver&#xff0c;使用Class.forName()方法加载特定的驱动程序&#xf…...

633. 平方数之和-LeetCode(C++)

633. 平方数之和 2024.9.11 题目 给定一个非负整数 c &#xff0c;你要判断是否存在两个整数 a 和 b&#xff0c;使得 a2 b2 c 。 0 < c < 2的31次方 - 1 示例 示例 1&#xff1a; 输入&#xff1a;c 5 输出&#xff1a;true 解释&#xff1a;1 * 1 2 * 2 5示…...

Linux shell编程学习笔记79:cpio命令——文件和目录归档工具(下)

在 Linux shell编程学习笔记78&#xff1a;cpio命令——文件和目录归档工具&#xff08;上&#xff09;-CSDN博客https://blog.csdn.net/Purpleendurer/article/details/142095476?spm1001.2014.3001.5501中&#xff0c;我们研究了 cpio命令 的功能、格式、选项说明 以及 cpi…...

《 C++ 修炼全景指南:七 》优先级队列在行动:解密 C++ priority_queue 的实现与应用

1、引言 在现代编程中&#xff0c;处理动态优先级队列的需求随处可见&#xff0c;例如任务调度、路径规划、数据压缩等应用场景都依赖于高效的优先级管理。C 标准库提供了 priority_queue 这一强大的工具&#xff0c;它的独特之处在于它的排序特性&#xff0c;priority_queue …...

通信工程学习:什么是HSS归属用户服务器

HSS&#xff1a;归属用户服务器 HSS&#xff08;归属用户服务器&#xff0c;Home Subscriber Server&#xff09;是IP多媒体子系统&#xff08;IMS&#xff09;中控制层的一个重要组成部分&#xff0c;它扮演着存储和管理用户相关信息的核心角色。以下是关于HSS归属用户服务器的…...

mysql workbench 如何访问远程数据库

要使用 MySQL Workbench 访问远程数据库&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;获取远程数据库的连接信息 首先&#xff0c;确保你有远程数据库的以下信息&#xff1a; 主机名&#xff08;Host&#xff09;&#xff1a;通常是服务器的 IP 地址或域…...

ICMAN触摸感应芯片方案

ICMAN触摸感应芯片 ICMAN触摸感应芯片采用先进的电容感应技术&#xff0c;能够精确检测和识别触摸动作。这一技术通过感应人体与传感器之间的微小电容变化来实现触控功能。相比传统的电阻式触控技术&#xff0c;电容感应技术具有更高的灵敏度和响应速度&#xff0c;能够提供更…...

面向个小微型企业的开源大模型(Qwen2等)商业化, AI部署成本分析与优化策略(费用分析、资源消耗分析)

小微企业AI大模型部署服务器解决方案:资源及成本分析 1.GPU-LLM技术依赖评估依据 在当前全球化的背景下,本地化需求日益凸显,无论是企业拓展国际市场还是个人用户追求更加贴近本土化的服务体验,都对技术的本地化部署提出了更高要求。随着人工智能(AI)技术的飞速发展,尤…...