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
相关文章:
C++套接字库sockpp介绍
sockpp是一个开源、简单、现代的C套接字库,地址为:https://github.com/fpagliughi/sockpp,最新发布版本为0.8.1,license为BSD-3-Clause。目前支持Linux、Windows、Mac上的IPv4、IPv6和Unix域套接字。其它*nix和POSIX系统只需很少的…...
Mac M2开发环境安装
持续更新 brew 安装 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"JAVA多版本环境 ## 终端下载安装 brew install --cask temurin8 brew install --cask temurin11 brew install --cask temurin17## vim ~/.…...
Linux各种版本安装详细步骤和root密码破解
文章目录 VMware新建虚拟机硬件设置设置虚拟网络挂载ISO文件 root密码破解 VMware新建虚拟机 硬件设置 设置虚拟网络 编辑>虚拟网络编辑器>VMnet8(NAT模式) 挂载ISO文件 加电>开启次虚拟机 第二项可以检查挂载上来的iso文件是否完整没有破坏 磁盘分区 选自定义分…...
Netty - 回顾Netty高性能原理和框架架构解析
文章目录 概述JDK 原生 NIO 程序的问题Why Netty使用场景Related ProjectsNetty 高性能设计I/O 模型【阻塞 I/O】:【I/O 复用模型】【基于 Buffer】 线程模型事件驱动模型Reactor 线程模型Netty的线程模型异步处理 Netty框架的架构设计功能特性模块组件Bootstrap、S…...
uni-app——項目day01
配置uni-app開發環境 uni-app快速上手 | uni-app官网 创建项目 图中四个划线就是要配置的地方. 选择vue2还是vue3看个人选择。 目录结构 但是现在新版本创建的项目已经没有components目录了,需要自己创建。 项目运行到微信开发者工具 使用git管理项目 node-mod…...
【Java、MongoDB】程序控制非关系数据库
步骤: (1)连接 连接字符串 (2)CRUD 类与接口 解析 (3)maven管理方法 依赖 <dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-legacy<…...
MySQL查询时间处理相关函数与方法实践笔记
1. 实践案例 在查询mysql数据库获取数据时,有这样一个需求:按每30分钟分组获取电量数据,形成1天48个数据点。 方法一: select hour(a.CreateTime) 时点,case when MINUTE(a.CreateTime)<30 then 1 else 2 end 半小时,sum(a…...
springboot全局拦截sql异常
起因:非法用户可通过特定的输入(如输入内容超长)等操作,使后台逻辑发生错误,从而使后台sql语句暴露至前台,进而为sql攻击提供条件 处理流程:经查找com.mysql.cj.jdbc.exceptions的父类为SQLException,在全局异常处理类中增加如下配置,经测试不起作用 ExceptionHandler(SQLExce…...
AlGaN/GaN HFET 五参数模型
标题:A Five-Parameter Model of the AlGaN/GaN HFET 来源:IEEE TRANSACTIONS ON ELECTRON DEVICES(15年) 摘要—我们引入了AlGaN/GaN异质结场效应晶体管(HFET)漏极电流Id(Vgs,Vds…...
矩阵的除法
B/A 如果矩阵A可逆,那么 证明: A/AB 如果矩阵A和B都可逆,那么 证明:...
Java中的 向上转型 | 向下转型
目录 一.向上转型 直接赋值 总结: 通过传参 通过返回值 二.向下转型 instanceof 一.向上转型 向上转型其实就是创建一个子类对象,并将其当作父类对象来使用,一般语法格式如下: 父类类型 对象名 new 子类类型() 一般有以…...
【华为OD机试AB高分必刷题目】朋友圈(C++-并查集Union-Find实现)
🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,高分通过! 文章目录 【华为OD机试AB高分必刷题目】朋友圈(C++-并查集Union-Find实现)题目描述解题思路C++题解代码代码OJ评判结果代码讲解寄语【华为OD机试AB高分…...
前端面试题之vue篇
vue基础 vue的基本原理 当一个Vue实例创建时,Vue会遍历data中的属性,用Object.defineProperty(Vue使用proxy)转换为getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的watcher程序实例…...
Java进阶(垃圾回收GC)——理论篇:JVM内存模型 垃圾回收定位清除算法 JVM中的垃圾回收器
前言 JVM作为Java进阶的知识,是需要Java程序员不断深度和理解的。 本篇博客介绍JVM的内存模型,对比了1.7和1.8的内存模型的变化;介绍了垃圾回收的语言发展;阐述了定位垃圾的方法,引用计数法和可达性分析发以及垃圾清…...
GaN HEMT 电容的分析建模,包括寄生元件
标题:Analytical Modeling of Capacitances for GaN HEMTs, Including Parasitic Components 来源:IEEE TRANSACTIONS ON ELECTRON DEVICES(14年) 摘要:本文提出了一种基于表面势的终端电荷和电容模型,包…...
Python实战 | 使用 Python 和 TensorFlow 构建卷积神经网络(CNN)进行人脸识别
专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https:/…...
JLink edu mini 10Pin接口定义
注意:SWD接口在阵脚2,4;而20Pin的SWD接口在阵脚7,9 参考:1 官网资料; 2 【润石RS0104YQ Demo开发板测试分享】J-Link EDU Mini调试5V系统_国产运算放大器_模拟开关_线性稳压器_电平转换器_小逻辑_比较器…...
compile: version “go1.19“ does not match go tool version “go1.18.1“
** 1 安装了新版本的go后 为什么go version 还是旧版本? ** 如果你已经按照上述步骤安装了新版本的 Go,但 go version 命令仍然显示旧版本,可能是因为你的环境变量设置不正确或未正确生效。你可以尝试以下方法来解决问题: 重新…...
spring boot security 自定义AuthenticationProvider
spring boot security 自定义AuthenticationProvider 基于 spring boot 3.x 场景实现 手机验证码登陆 实现 CaptureCodeAuthenticationFilter public class CaptureCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {private static final Strin…...
某电力设计公司绩效考核优化项目成功案例纪实
——引入角色定位考核法,建立多维度评价体系,支持业务转型后的客观评价 【客户行业】电力行业 【问题类型】绩效考核 【客户背景及现状分析】 某电力设计公司成立于2000年左右,是一家从事输变电工程勘察、设计、咨询的专业公司,…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
