【C++boost::asio网络编程】有关socket的创建和连接的笔记
socket的创建和连接
- tcp客户端创建端点
- tcp服务端创建端点
- 创建socket
- 创建TCP 服务器端的 acceptor 套接字
- 创建 acceptor 套接字并绑定
- 客户端连接到服务器
- 通过ip地址解析
- 通过域名解析
- 服务端接收新连接
tcp客户端创建端点
int client_end_point()
{std::string raw_ip_address = "127.0.0.1";unsigned short prot_num = 8888;boost::system::error_code ec;boost::asio::ip::address ip_address = boost::asio::ip::address::from_string(raw_ip_address, ec);if (ec.value() != 0){std::cout << "Failed to parse the IP address.Error code = " << ec.value() << ".Message is " << ec.message();return ec.value();}boost::asio::ip::tcp::endpoint endpoint(ip_address, prot_num);return 0;
}
std::string raw_ip_address和unsigned short prot_num分别代表了ip地址和端口号,其中127.0.0.1为本地回环地址,也叫做localhost
cboost::system::error_code ec用来表示可能出现的错误。Boost.Asio 使用这个对象来存储错误信息,例如网络操作中可能发生的错误
boost::asio::ip::address ip_address = boost::asio::ip::address::from_string(raw_ip_address, ec);则是将字符串类型的ip地址解析为boost库中更为通用的boost::asio::ip::address 类型的对象
boost::asio::ip::tcp::endpoint endpoint(ip_address, prot_num);该语句使用ip_address 和prot_num 创建了一个 TCP 端点(tcp::endpoint)。端点是网络通信中表示地址和端口的对象,通常用于设置连接目标。ip_address 是通过前面解析得到的 IP 地址。prot_num 是端口号,表示服务监听的端口。
tcp服务端创建端点
int server_end_point()
{unsigned port_num = 8888;//端口号boost::asio::ip::address ip_address = boost::asio::ip::address_v6::any();boost::asio::ip::tcp::endpoint endpoint(ip_address, port_num);return 0;
}
boost::asio::ip::address_v6::any() 是一个特殊的 IPv6 地址,表示任意可用的地址,通常用于服务器端监听所有可用的 IPv6 地址。如果是 IPv4 地址的话,则使用 boost::asio::ip::address_v4::any()
创建socket
int create_tcp_socket()
{boost::asio::io_context ioc;boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();boost::system::error_code ec;boost::asio::ip::tcp::socket sock(ioc);sock.open(protocol, ec);if (ec.value() != 0){std::cout<< "Failed to open the socket! Error code = "<< ec.value() << ". Message: " << ec.message();return ec.value();}return 0;
}
boost::asio::io_context 是 Boost.Asio 中用于执行异步操作的核心对象。它是所有异步操作的调度中心,负责调度和执行异步事件
boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();
这段代码主要意思是选择TCP协议的版本,当使用tcp::v4()代表使用的是TCP协议的IPV4版本,如果使用的是tcp::v6()则代表选择的是IPV6
boost::asio::ip::tcp::socket sock(ioc);
以上代码创建了一个 boost::asio::ip::tcp::socket 类型的套接字对象 sock。该套接字是基于之前创建的 ioc(io_context)对象进行初始化的。ioc 是 io_context 对象,它在后台驱动异步操作,而套接字则是与网络通信的实体,能够接收和发送数据
sock.open(protocol, ec);
sock.open(protocol, ec) 尝试打开一个 TCP 套接字。这里的 protocol 是之前定义的 IPv4 协议(boost::asio::ip::tcp::v4())。
如果打开成功,sock 将变为可用状态,允许进行后续的读写操作。如果失败,ec 将保存错误码和错误信息
创建TCP 服务器端的 acceptor 套接字
int create_acceptor_socket()
{boost::asio::io_context ioc;boost::asio::ip::tcp::acceptor acceptor(ioc);boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();boost::system::error_code ec;acceptor.open(protocol, ec);if (ec.value() != 0){std::cout << "false" << std::endl;return ec.value();}return 0;
}
boost::asio::ip::tcp::acceptor acceptor(ioc);
boost::asio::ip::tcp::acceptor 是一个用于监听客户端连接请求的对象。在这里,acceptor 对象会依赖于 ioc(io_context)来执行其异步操作。acceptor 的作用是等待客户端发起连接,并接受连接。
boost::asio::ip::tcp protocol = boost::asio::ip::tcp::v4();
boost::asio::ip::tcp::v4() 表示使用 IPv4 协议类型。这里创建了一个表示 IPv4 协议的 protocol 对象。可以理解为告诉 acceptor 套接字它应该使用 IPv4 协议来进行通信。
Boost.Asio 同时支持 IPv4 和 IPv6,这里选择了 v4(),意味着服务器将只监听 IPv4 地址
acceptor.open(protocol, ec);
以上代码 是用来打开 acceptor 套接字的函数。在这里,protocol 参数指定了使用的协议(IPv4),ec 用于捕获错误代码。该操作会尝试在指定协议(IPv4)下打开一个套接字,并让其开始监听传入连接的请求。
如果 acceptor.open() 操作失败,错误信息会被记录在 ec 中。
这段代码并没有绑定 acceptor 到具体的地址和端口。通常情况下,acceptor.open() 之后,还需要通过 acceptor.bind() 或直接在 acceptor 构造函数中指定一个端点(IP 地址和端口)来完成绑定。
还有一种更加方便的方式创建acceptor 套接字
int create_acceptor_socket()
{boost::asio::io_context ioc;boost::asio::ip::tcp::acceptor a(ioc,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),8888));
return 0;
}
acceptor的构造函数接收了两个参数
ioc:即之前创建的 boost::asio::io_context 对象。acceptor 需要依赖它来执行后续的 I/O 操作。boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 8888):这是一个endpoint对象,表示监听的具体地址和端口
创建 acceptor 套接字并绑定
int bind_acceptor_socket()
{boost::asio::io_context ioc;unsigned short prot_num = 8888;boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address_v4::any(), prot_num);boost::asio::ip::tcp::acceptor a(ioc, ep.protocol());boost::system::error_code ec;a.bind(ep,ec);if (ec.value() != 0) {std::cout << "Failed to bind the acceptor socket."<< "Error code = " << ec.value() << ". Message: "<< ec.message();return ec.value();}return 0;
}
为什么这里没有对acceptor的open操作?
通常情况下,open 操作用来显式地打开一个套接字并指定其协议类型。在之前创建boost::asio::ip::tcp::acceptor对象时只传递了一格参数ioc而没有指定协议类型(是IPV4还是IPV6?),所以需要手动显示open,但是这里boost::asio::ip::tcp::acceptor a(ioc, ep.protocol());创建时传递了协议类型,它就是在构造函数中自动完成open操作
客户端连接到服务器
通过ip地址解析
int connect_to_end()
{unsigned short prot_num = 8888;std::string ip = "127.0.0.1";try{boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(ip), prot_num);boost::asio::io_context ioc;boost::asio::ip::tcp::socket sock(ioc, ep.protocol());sock.connect(ep);}catch (const boost::system::system_error& e){std::cout << "Error occured! Error code = " << e.code() << ".Message:" << e.what();return e.code().value();}return 0;
}
通过域名解析
int dns_connect_to_end()
{std::string host = "www.baidu.com";std::string port_num = "8888";boost::asio::io_context ioc;boost::asio::ip::tcp::resolver::query resolver_query(host, port_num, boost::asio::ip::tcp::resolver::query::numeric_service);boost::asio::ip::tcp::resolver resolver(ioc);try{boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(resolver_query);boost::asio::ip::tcp::socket sock(ioc);boost::asio::connect(sock, it);}catch (boost::system::system_error& e){std::cout << "Error occured! Error code = " << e.code() << ".Message:" << e.what() << std::endl;return e.code().value();}return 0;
}
boost::asio::ip::tcp::resolver::query resolver_query(host, port_num, boost::asio::ip::tcp::resolver::query::numeric_service);
这里创建了一个 resolver_query 对象,指定了要解析的域名 host 和端口号 port_num。
boost::asio::ip::tcp::resolver::query 是 Boost.Asio 中用于描述解析查询的类,它包含了域名和端口信息,告诉解析器要解析哪个主机的 IP 地址。
boost::asio::ip::tcp::resolver::query::numeric_service 表示请求解析服务的端口号为数值类型,确保解析器解析的是数字形式的端口号。
boost::asio::ip::tcp::socket sock(ioc);
boost::asio::connect(sock, it);
boost::asio::ip::tcp::socket sock(ioc) 创建了一个 TCP 套接字 sock,并使用 ioc(I/O 服务对象)进行初始化。
boost::asio::connect(sock, it) 尝试连接到解析出来的第一个 IP 地址。这里,it 是从 resolver.resolve() 返回的迭代器,表示解析到的 IP 地址列表。connect 会逐个尝试列表中的 IP 地址,直到找到一个能够成功连接的地址。
服务端接收新连接
int accept_new_connection()
{const int BACKLOG_SIZE = 30;boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address_v4::any(), 8888);boost::asio::io_context ioc;try{boost::asio::ip::tcp::acceptor ac(ioc,ep.protocol());ac.bind(ep);ac.listen(BACKLOG_SIZE);boost::asio::ip::tcp::socket sock(ioc);ac.accept(sock);}catch (boost::system::system_error& e){std::cout << "Error occured! Error code = " << e.code() << ".Message:" << e.what() << std::endl;return e.code().value();}return 0;
}
BACKLOG_SIZE 设置为 30,表示服务器在等待连接时能够排队的最大连接数。这是 TCP 协议栈的一个参数,通常设置为比实际预期连接数稍大的值,防止过多的连接被拒绝。
boost::asio::ip::tcp::socket sock(ioc);
ac.accept(sock);
boost::asio::ip::tcp::socket sock(ioc); 创建一个新的 TCP 套接字 sock,用于与连接的客户端进行通信。这个套接字是通过 ioc(I/O 上下文)初始化的。
ac.accept(sock); 调用 accept() 方法等待接受客户端的连接。当有客户端尝试连接到指定端口时,accept() 会阻塞直到接收到连接请求。成功后,sock 就与客户端建立了连接,并且可以用它来进行数据传输。
相关文章:
【C++boost::asio网络编程】有关socket的创建和连接的笔记
socket的创建和连接 tcp客户端创建端点tcp服务端创建端点创建socket创建TCP 服务器端的 acceptor 套接字创建 acceptor 套接字并绑定客户端连接到服务器通过ip地址解析通过域名解析 服务端接收新连接 tcp客户端创建端点 int client_end_point() {std::string raw_ip_address …...
超级灵感:前端页面功能统一管理方案
前端页面功能统一管理方案 引言 我和朋友聊天想到一个灵感,关于支付状态机管理,这个类可以让我们知道具体上一个状态和下一个状态,这是由于那个事件触发改变,这个功能设计非常好! 从而讨论出为什么我们不能把某一个…...
力扣第 77 题 组合
题目描述 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按任意顺序返回答案。 示例 示例 1 输入: n 4, k 2输出: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]示例 2 输入: n 1, k …...
(超详细图文)PLSQL Developer 配置连接远程 Oracle 服务
1、下载配置文件 (超详细图文详情)Navicat 配置连接 Oracle-CSDN博客 将下载的文件解压到单独文件夹,如:D:\App\App_Java\Oracle\instantclient-basic-windows.x64-19.25.0.0.0dbru 2、配置 打开 PLSQL Developer,登…...
元器件选型与参数13 电源的分类-线性电源参数 RT9013 AMS1117 PCB布局布线
目录 一、线性电源 1、重要参数 2、线性电源效率一定低吗 3、线性电源并联扩流 4、常见电路 RT9013-LDO AMS1117-xx-LDO 5、布局布线 6、外置输入与电池供电 7、单片机控制其他模组供电实现低功耗 二、开关电源与线性电源配合 1、高效率与低噪声 DC-DC电源大致分为…...
RHEL7+Oracle11.2 RAC集群-多路径(multipath+udev)安装步骤
RHEL7Oracle11.2RAC集群-多路径(multipathudev)安装 配置虚拟存储 使用StarWind Management Console软件,配置存储 dggrid1: 1g*3 Dggrid2: 1g*3 Dgsystem: 5g*1 系统表空间,临时表空间,UNDO,参数文件…...
每日速记10道java面试题03
其他资料 每日速记10道java面试题01-CSDN博客 每日速记10道java面试题02-CSDN博客 目录 一、你使用过java的反射机制吗?如何应用反射? 二、什么是泛型?泛型的作用是什么? 三、java的泛型擦除是什么? 四、Java 中…...
Vue 3 的双向绑定原理
Vue 3 的双向绑定原理是基于 响应式系统 和 数据劫持 技术来实现的。在 Vue 3 中,双向绑定通常是通过 v-model 指令来完成的,它本质上是数据的双向同步:当数据改变时,视图自动更新,反之,视图的修改也会更新…...
如何使用 Chrome 无痕浏览模式访问网站?
无痕浏览(Incognito Mode)是 Google Chrome 浏览器提供的一种隐私保护功能,它允许用户在一个独立的会话中浏览网页,而不会记录用户的浏览历史、下载历史、表单数据等。这对于希望保护个人隐私或进行临时性匿名浏览的用户来说非常有…...
Idea 2024.3 突然出现点击run 运行没有反应,且没有任何提示。
写这篇文章的目的是为了提供一个新的解决思路,因为存在同病不同原因。 如果你进行了1. 检查运行配置 (Run Configuration) 2. 清理和重建项目 3. 清除缓存并重启 IDEA 4.排除kotlin 5.重装idea等等操作之后仍然没有解决,可以试着按一下步骤进行解决。 检…...
【小白学机器学习36】关于独立概率,联合概率,交叉概率,交叉概率和,总概率等 概念辨析的例子
目录 1 先说结论 2 联合概率 3 边缘概率 4 (行/列)边缘概率的和 总概率1 5 条件概率 5.1 条件概率的除法公式 5.2 条件概率和联合概率区别 1 先说结论 关于独立概率,联合概率,交叉概率,交叉概率和,总概率 类型含义 …...
Spring Boot 项目——分层架构
在创建一个 Spring Boot 项目时,为了提高代码的可维护性、可扩展性和清晰度,通常会按照一定的分层架构进行设计。常见的分层架构包括以下几层: 1. Controller 层(Web 层) 作用:接收用户请求,并…...
wordpress网站首页底部栏显示网站备案信息
一、页脚文件footer.php 例如,wordpress主题使用的是simple-life主题,服务器IP为192.168.68.89,在wordpress主题文件中有个页脚文件footer.php,这是一个包含网站页脚代码的文件。 footer.php 路径如下: /www/wwwroot/192.168.68…...
python面向对象编程练习
学生成绩管理系统 定义一个Student类,包括属性(姓名、成绩)和方法(设置成绩、获取成绩、计算平均成绩)。 实例化多个学生对象并调用方法。 功能说明: Student 类: init(self, name):…...
OpenCV_Code_LOG
孔洞填充 void fillHole(const Mat srcBw, Mat &dstBw) {Size m_Size srcBw.size();Mat TempMat::zeros(m_Size.height2,m_Size.width2,srcBw.type());//延展图像srcBw.copyTo(Temp(Range(1, m_Size.height 1), Range(1, m_Size.width 1)));cv::floodFill(Temp, Point(…...
力扣第 74 题是 搜索二维矩阵
题目描述 给定一个 m x n 的矩阵 matrix 和一个目标值 target,请你编写一个函数来判断目标值 target 是否在矩阵中。 每行的元素按升序排列。每列的元素按升序排列。 示例 1 输入: matrix [[1, 4, 7, 11],[2, 5, 8, 12],[3, 6, 9, 16],[10, 13, 14…...
[极客大挑战 2019]BabySQL--详细解析
信息搜集 进入界面: 输入用户名为admin,密码随便输一个: 发现是GET传参,有username和password两个传参点。 我们测试一下password点位能不能注入: 单引号闭合报错,根据报错信息,我们可以判断…...
实现Linux平台自定义协议族
一 简介 我们常常在Linux系统中编写socket接收TCP/UDP协议数据,大家有没有想过它怎么实现的,如果我们要实现socket接收自定义的协议数据又该怎么做呢?带着这个疑问,我们一起往下看吧~~ 二 Linux内核函数简介 在Linux系统中要想…...
RL78/G15 Fast Prototyping Board Arduino IDE 平台开发过程
这是一篇基于RL78/G15 Fast Prototyping Board的Arduino IDE开发记录 RL78/G15 Fast Prototyping Board硬件简介(背景)基础测试(方法说明/操作说明)开发环境搭建(方法说明/操作说明代码结果)Arduino IDE RL…...
YOLOv11 NCNN安卓部署
YOLOv11 NCNN安卓部署 前言 yolov11 NCNN安卓部署 目前的帧率可以稳定在20帧左右,下面是这个项目的github地址:https://github.com/gaoxumustwin/ncnn-android-yolov11 上面的检测精度很低时因为这个模型只训练了5个epoch,使用3090训练一个…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
