C++套接字库sockpp介绍

      sockpp是一个开源、简单、现代的C++套接字库,地址为:https://github.com/fpagliughi/sockpp,最新发布版本为0.8.1,license为BSD-3-Clause。目前支持Linux、Windows、Mac上的IPv4、IPv6和Unix域套接字。其它*nix和POSIX系统只需很少的修改或无需修改即可工作。
      1.套接字基类包装(wrap)系统套接字句柄,并维持其生命周期。当C++对象超出范围时,它会关闭底层套接字句柄。套接字对象通常是可移动的,但不可复制。可以使用 std::move()将套接字从一个作用域(或线程)传输到另一个作用域。
      2.库中的所有代码都位于sockpp C++命名空间内。
      3.TCP和其它"流"网络应用程序通常设置为服务器或客户端。接受器用于创建TCP/流服务器。它绑定一个地址并侦听已知端口以接受传入连接。 当连接被接受时,会创建一个新的流式套接字。该新套接字可以直接处理或移动到线程(或线程池)进行处理。
      相反,要创建TCP客户端,需要创建连接器对象并将其连接到已知地址(通常是主机和套接字)的服务器。连接后,套接字是一种流式套接字,可以直接用于读写。
      对于IPv4,sockpp::tcp_acceptor和sockpp::tcp_connector类分别用于创建服务器和客户端。它们使用sockpp::inet_address类来指定由32位主机地址和16位端口号组成的端点地址。
      sockpp::tcp_acceptor通常位于一个循环中接受新连接,并将它们传递给另一个进程、线程或线程池以与客户端交互
      TCP客户端稍微简单一些,创建一个sockpp::tcp_connector对象并连接,然后可以直接读写数据。
      4.每个套接字类的默认构造函数不执行任何操作,只是将底层句柄设置为INVALID_SOCKET。它们不创建套接字对象。
      5.套接字对象不是线程安全的。想要有多个线程从套接字读取或写入套接字的应用程序应该使用某种形式的序列化,例如std::mutex来保护访问。套接字可以安全地从一个线程移动到(moved)另一个线程。这是服务器的一种常见模式,它使用一个线程接受传入连接,然后将新套接字传递给另一个线程或线程池进行处理。
      由于套接字无法复制,唯一的选择是将套接字移动到这样的函数。这是一种常见的模式,尤其是在客户端应用程序中,让一个线程从套接字读取数据,另一个线程向套接字写入数据。在这种情况下,底层套接字句柄可以被认为是线程安全的(一个读线程和一个写线程)。但即使在这种情况下,sockpp::socket对象仍然不是线程安全的,特别是由于缓存的错误值(cached error value)。写入线程可能会看到读取线程上发生的错误,反之亦然。
      这种情况的解决方案是使用socket::clone()方法来复制套接字。这将使用系统的dup()函数或类似的函数创建另一个带有套接字句柄的重复副本的套接字。这样做的另一个好处是套接字的每个副本都可以保持独立的生命周期。在两个对象超出范围之前,底层套接字不会关闭。

      在Windows和Linux上编译的sockpp的shell脚本如下:

#! /bin/bashif [ $# != 2 ]; thenecho "Error: requires two parameters: 1: windows or linux; 2: release or debug"echo "For example: $0 windows debug"exit -1
fiif [ $1 != "windows"  ] && [ $1 != "linux" ]; thenecho "Error: the first parameter can only be windows or linux"exit -1
fiif [ $2 != "debug" ] && [ $2 != "release" ]; thenecho "Error: the second parameter can only be debug or release"exit -1
fiif [ $1 == "windows" ] && [ $2 == "debug" ]; thencmake \-G"Visual Studio 17 2022" -A x64 \-DCMAKE_BUILD_TYPE=Debug \-DCMAKE_CONFIGURATION_TYPES=Debug \-DSOCKPP_BUILD_SHARED=OFF \-DSOCKPP_BUILD_STATIC=ON \-DSOCKPP_BUILD_EXAMPLES=ON \-DCMAKE_INSTALL_PREFIX=install/debug \-Bbuild \.cmake --build build/ --target install --config debug
fiif [ $1 == "windows" ] && [ $2 == "release" ]; thencmake \-G"Visual Studio 17 2022" -A x64 \-DCMAKE_BUILD_TYPE=Release \-DCMAKE_CONFIGURATION_TYPES=Release \-DSOCKPP_BUILD_SHARED=OFF \-DSOCKPP_BUILD_STATIC=ON \-DSOCKPP_BUILD_EXAMPLES=ON \-DCMAKE_INSTALL_PREFIX=install/release \-Bbuild \.cmake --build build/ --target install --config release
fiif [ $1 == "linux" ] && [ $2 == "debug" ]; thencmake \-DCMAKE_BUILD_TYPE=Debug \-DSOCKPP_BUILD_SHARED=OFF \-DSOCKPP_BUILD_STATIC=ON \-DSOCKPP_BUILD_EXAMPLES=ON \-DCMAKE_INSTALL_PREFIX=install/debug \-Bbuild \.cmake --build build/ --target install --config debug
fiif [ $1 == "linux" ] && [ $2 == "release" ]; thencmake \-DCMAKE_BUILD_TYPE=Release \-DSOCKPP_BUILD_SHARED=OFF \-DSOCKPP_BUILD_STATIC=ON \-DSOCKPP_BUILD_EXAMPLES=ON \-DCMAKE_INSTALL_PREFIX=install/release \-Bbuild \.cmake --build build/ --target install --config release
firc=$?
if [[ ${rc} != 0 ]]; thenecho "Error: please check: ${rc}"exit ${rc}
fi

      以下为IPv4的测试代码:

      1.客户端测试代码如下:

int test_sockpp_client()
{sockpp::initialize();sockpp::tcp_connector conn({host, port});if (!conn) {std::cerr << "Error: connecting to server at: "<< sockpp::inet_address(host, port)<< ", message: " << conn.last_error_str() << std::endl;return -1;}std::cout << "created a connection from: " << conn.address() << std::endl;std::cout << "created a connection to " << conn.peer_address() << std::endl;// set a timeout for the responsesif (!conn.read_timeout(std::chrono::seconds(5))) {std::cerr << "Error: setting timeout on TCP stream: " << conn.last_error_str() << std::endl;}const std::vector<std::string> addr{"csdn", "github", "gitlab"};std::unique_ptr<unsigned char[]> buf(new unsigned char[len]);int index{0};std::atomic<bool> quit{ false };std::thread th([&quit] {std::this_thread::sleep_for(std::chrono::seconds(20));quit = true;});while (true) {if (quit) break;auto ret = conn.write(addr[index]);if (ret != addr[index].size()) {std::cerr << "Error: writing to the TCP stream: " << conn.last_error_str() << std::endl;break;}memset(buf.get(), 0, len);ret = conn.read(buf.get(), len);if (ret == -1) {std::cerr << "Error: reading from TCP stream: " << conn.last_error_str() << std::endl;break;}std::cout << addr[index] << ": " << buf.get() << std::endl;if (++index == addr.size()) index = 0;std::this_thread::sleep_for(std::chrono::seconds(1));}th.join();return 0;
}

      2.服务器端测试代码如下:

int test_sockpp_server()
{sockpp::initialize();sockpp::tcp_acceptor acc(port);if (!acc) {std::cerr << "Error: creating the acceptor: " << acc.last_error_str() << std::endl;return -1;}while (true) {sockpp::inet_address peer;// accept a new client connectionsockpp::tcp_socket sock = acc.accept(&peer);std::cout << "received a connection request from: " << peer << std::endl;if (!sock) {std::cerr << "Error: accepting incoming connection: " << acc.last_error_str() << std::endl;}else {// create a thread and transfer the new stream to itstd::thread th2(run_echo, std::move(sock));th2.detach();}}return 0;
}

      3.辅助code如下所示:

namespace {constexpr char* host{"127.0.0.1"};
constexpr in_port_t port{ 8888 };
constexpr int len {64};void run_echo(sockpp::tcp_socket sock)
{std::cout << "thread id: " << std::this_thread::get_id() << std::endl;std::map<std::string, std::string> addr;addr["csdn"] = "https://blog.csdn.net/fengbingchun";addr["github"] = "https://github.com/fengbingchun";std::unique_ptr<unsigned char[]> buf(new unsigned char[len]);while (true) {memset(buf.get(), 0, len);auto ret = sock.read(buf.get(), len);if (ret == -1) {std::cerr << "Error: reading from TCP stream: " << sock.last_error_str() << std::endl;break;}auto it = addr.find(std::string((char*)buf.get()));if (it != addr.end()) {sock.write(it->second);}elsesock.write("unkonwn");}
}} // namespace

      Windows上执行结果如下所示:模拟1个服务器端,3个客户端

      Linux上执行结果如下图所示:模拟1个服务器端,3个客户端

      GitHub:https://github.com/fengbingchun/OpenSSL_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/188985.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

获取请求IP以及IP解析成省份

某些业务需要获取请求IP以及将IP解析成省份之类的&#xff0c;于是我写了一个工具类&#xff0c;可以直接COPY /*** IP工具类* author xxl* since 2023/11/9*/ Slf4j public class IPUtils {/*** 过滤本地地址*/public static final String LOCAL_ADDRESS "127.0.0.1&quo…

【数据结构初阶】算法的时间复杂度和空间复杂度

各位读者老爷好&#xff01;现在鼠鼠我呀来浅谈一下数据结构初阶中的一个知识点&#xff1a;算法的时间复杂度和空间复杂度&#xff0c;希望对你有所帮助。 在浅谈时间复杂度和空间复杂度之前&#xff0c;咱们可以来了解一下一下几个概念&#xff1a; 1.什么是数据结构 数据结…

Http状态码502常见原因及排错思路(实战)

Http状态码502常见原因及排错思路 502表示Bad Gateway。当Nginx返回502错误时&#xff0c;通常表示Nginx作为代理服务器无法从上游服务器&#xff08;如&#xff1a;我们的后端服务器地址&#xff09;获取有效的响应。导致这种情况的原因有很多&#xff1a; 后端服务器故障ngin…

3 分钟看完 NVIDIA GPU 架构及演进

近期随着 AI 市场的爆发式增长&#xff0c;作为 AI 背后技术的核心之一 GPU&#xff08;图形处理器&#xff09;的价格也水涨船高。GPU 在人工智能中发挥着巨大的重要&#xff0c;特别是在计算和数据处理方面。目前生产 GPU 主流厂商其实并不多&#xff0c;主要就是 NVIDIA、AM…

React 递归手写流程图展示树形数据

需求 根据树的数据结构画出流程图展示&#xff0c;支持新增前一级、后一级、同级以及删除功能&#xff08;便于标记节点&#xff0c;把节点数据当作label展示出来了&#xff0c;实际业务中跟据情况处理&#xff09; 文件结构 初始数据 [{"ticketTemplateCode": &…

链表经典OJ题(链表回文结构,链表带环,链表的深拷贝)

目录 前言 1.反转一个单链表。 2. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。 3.链表的回文结构。 4.链表带环问题&#xff08;*****&#xff09; 4.1是否带环 4.2 入环的节点 5.随机链表的复制&#xff08;链表的深拷贝&#xff09; 前言…

kubernetes (k8s)的使用

一、kubernetes 简介 谷歌2014年开源的管理工具项目&#xff0c;简化微服务的开发和部署。 提供功能&#xff1a;自愈和自动伸缩、调度和发布、调用链监控、配置管理、Metrics监控、日志监控、弹性和容错、API管理、服务安全等。官网&#xff1a;https://kubernetes.io/zh-cn…

KubeSphere v3.4.0 部署K8S Docker + Prometheus + grafana

KubeSphere v3.4.0 部署K8S 1、整体思路2、修改linux主机名3、 离线安装3.1 问题列表3.2 执行命令成功列表 1、整体思路 将KubeSphere v3.4.0 安装包传输到其中一台机器修改Linux主机名&#xff08;选取3台&#xff0c;修改为master01、master02、master03&#xff09;安装官方…

2023-11-12 LeetCode每日一题(Range 模块)

2023-03-29每日一题 一、题目编号 715. Range 模块二、题目链接 点击跳转到题目位置 三、题目描述 Range模块是跟踪数字范围的模块。设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们。 半开区间 [left, right) 表示所有 left < x < right 的实数 x 。 实…

Java必刷入门递归题×5(内附详细递归解析图)

目录 1.求N的阶乘 2.求12...N的和 3.顺序打印数字的每一位 4.求数字的每一位之和 5.求斐波拉契数列 1.求N的阶乘 &#xff08;1&#xff09;解析题目意思 比如求5的阶乘&#xff0c;符号表示就是5&#xff01;&#xff1b;所以5&#xff01;5*4*3*2*1我们下面使用简单的…

Android中Toast与Snack

1. Toast : 使用Toast类的makeText()方法创建Toast对象&#xff0c;makeText()方法有两个参数&#xff0c;第一个参数为显示Tosat的上下文环境&#xff0c;第二个参数为显示时长&#xff08; Toast.LENGTH_LONG 或 Toast.LENGTH_SHORT &#xff09;。 使用Toast类的show()方法…

【ubuntu 快速熟悉】

ubuntu 快速熟悉 2.ubuntu桌面管理器3.ubuntu常见文件夹说明4.ubuntu任务管理器4.1 gnome桌面的任务管理器4.2 实时监控GPU4.3 top 命令 5.ubuntu必备命令5.1 .deb文件5.2 查找命令5.2.1 find文件搜索5.2.2 which查找可执行文件的路径5.2.3 which的进阶&#xff0c;whereis5.2.…

【Spring】SpringBoot配置文件

文章目录 1. 配置文件格式2. properties 配置⽂件说明2.1 properties 基本语法2.2 读取配置文件2.3 properties 缺点分析 3. yml 配置文件说明3.1 yml 基本语法3.2 读取配置文件3.3 PostConstruct 注解3.4 配置null和空格3.5 value值加单双引号3.6 配置对象3.7 配置集合3.8 配置…

环形链表解析(c语言)c语言版本!自我解析(看了必会)

目录 1.判断一个表是否是环形链表&#xff01; 代码如下 解析如下 2.快指针的步数和慢指针的步数有什么影响&#xff08;无图解析&#xff09; 3.怎么找到环形链表的入环点 代码如下 解析如下 1.判断一个表是否是环形链表&#xff01; 代码如下 bool hasCycle(struct L…

Leetcode—69.x的平方根【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—69.x的平方根 直接法实现代码 int mySqrt(int x) {long long i 0;while(i * i < x) {i;}if(i * i > x) {return i - 1;}return i; }运行结果 二分法实现代码 int mySqrt(int x) {long long left 0, right (l…

自动化测试(Java+eclipse)教程

webdriver环境配置 1.下载chromedriver到本地&#xff08;一定要选择和自己浏览器相对应的版本chromedriver下载地址&#xff09; 2.加入到环境变量path中 webdriver工作原理 创建web自动化测试脚本 1.Maven项目创建 File->New->project->(搜索maven)选择maven pr…

功能案例 -- 通过开关,改变白天和黑夜

效果展示 代码展示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>:root {--default-bac-color: #f…

会员题-力扣408-有效单词缩写

有效单词缩写 字符串可以用 缩写 进行表示&#xff0c;缩写 的方法是将任意数量的 不相邻 的子字符串替换为相应子串的长度。例如&#xff0c;字符串 “substitution” 可以缩写为&#xff08;不止这几种方法&#xff09;&#xff1a; “s10n” (“s ubstitutio n”) “sub4…

基于STM32单片机抢答器设计

**单片机设计介绍&#xff0c; 基于STM32单片机抢答器设计-Proteus仿真 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于STM32单片机的抢答器设计可以用于教育和培训场景中的抢答游戏或考试环节。以下是一个基本的介绍设计步骤…

手摸手入门Springboot+Grafana10.2接收JSON

JSON&#xff08;JavaScript Object Notation, JS对象简谱&#xff09;是一种轻量级的数据交换格式。它基于 ECMAScript&#xff08;European Computer Manufacturers Association, 欧洲计算机协会制定的js规范&#xff09;的一个子集&#xff0c;采用完全独立于编程语言的文本…