【C++】【网络】【Linux系统编程】单例模式,加锁封装TCP/IP协议套接字
目录
引言
获取套接字
绑定套接字
表明允许监听
单例模式设计
完整代码示例
个人主页:东洛的克莱斯韦克-CSDN博客
引言
有关套接字编程的细节和更多的系统调用课参考《UNIX环境高级编程》一书,可以在如下网站搜索电子版,该书在第16章详细的介绍了各种接口。
Jiumo Search 鸠摩搜索 - 文档搜索引擎 (jiumodiary.com)
而在实际的编程中,总是用系统调用的接口难免会有些繁琐。我们可以根据自己的需求,用面向对象的思想封装出接口简洁的类。
也可以把类设计成单例,以组件的形式供上层使用。而上层坐拥下三层协议栈,无需关心网络通信的细节。
获取套接字
首先要用socket接口获取套接字文件描述符
int fd = socket(AF_INET, SOCK_STREAM, 0)
AF_INET表示IPv4因特网域
SOCK_STREAM表示该套接字的类型是全双工,面向字节流和链接的
第三个参数 0 表示根据前两个参数选择默认的协议,此时选择的就是TCP/IPv4协议栈
绑定套接字
bind(_socket_fd, (const struct sockaddr *)&address, (socklen_t)sizeof(address))
绑定套接字之前先用 struct sockaddr_in 结构体填充地址信息。
IPv4因特网域用struct sockaddr_in结构体填充,IPv6因特网域用struct sockaddr_in6结构体填充,为了使不同的地址格式能和套接字绑定,需要把对应的结构体强转成通用地址结构struct sockaddr。
struct sockaddr_in address;memset(&address, 0, sizeof(address)); // 把结构体初始化为0address.sin_family = AF_INET; // IPv4协议家族address.sin_addr.s_addr = INADDR_ANY; // 服务器选择任意IP地址接收请求address.sin_port = htons(_port); // 端口号信息,网络序列
填充字段时,需要用htons()函数把端口号改为网络字节序列。在填充之前最好初始化结构体。
INADDR_ANY表示套接字可以接收上层进程所在服务器的任意一个IP地址(公网IP),一台服务器可能会配置多个IP地址。
表明允许监听
listen(_socket_fd, 5)
第一个参数是网络文件描述符。
第二个参数提供了一个提示给系统,表明这个套接字所期望的、还未处理的(即还在等待被接受的连接)连接请求的最大队列长度。换句话说,它告诉系统内核为这个套接字分配多大的空间来存储尚未处理的连接请求。第二个参数不是严格遵守的。
单例模式设计
我们需要把类的构造函数,拷贝函数,赋值重载设为私有。在类似添加一个该类类型的指针,该指针是静态的并且是私有成员。
那么只给外面暴露一个获取该指针的接口,并且只能被获取一次。
获取指针的接口就需要加锁,防止并发问题。【Linux】用5万字满足你对线程的所有♥幻想♥——【线程概念】【线程安全】【多线程并发】【互斥量】【条件变量】【信号量】【锁的原理】【各种锁】【生产者消费者模型】【读者写者问题】-CSDN博客
完整代码示例
套接字代码已经在网络环境中测试过了~

日志代码
//日志打印
#pragma once
#include <iostream>
#include <string>
#include <ctime>
#define INFO 1
#define WARNING 2
#define ERROR 3
#define FATAL 4
#define LOG(level, message) Log(#level, message, __FILE__, __LINE__)void Log(std::string level, std::string message, std::string file_name, int line)
{std::cerr << "[" << level << "]" << "[" << time(nullptr) << "]" << "[" << message << "]" << "[" << file_name << "]" << "[" << line << "]" << std::endl;
}
套接字代码
#pragma once // 防止头文件被重复包含
#include <sys/socket.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <memory>
#include <pthread.h>
#include "log.hpp"#define BACKLOG 5 // 全连接队列最小值
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;class tcp_serve
{public:static tcp_serve *git_tcp_object(int port) // 获取单例实例{if (tcp_ptr == nullptr){pthread_mutex_lock(&mutex); // 加锁if (tcp_ptr == nullptr){tcp_ptr = new tcp_serve(port);tcp_ptr->initserve();}pthread_mutex_unlock(&mutex); // 解锁}return tcp_ptr;}int git_socket_fd(){return _socket_fd;}private:void initserve(){Socket();Bind();Listen();}tcp_serve(int port): _port(port), _socket_fd(-1){}~tcp_serve(){}tcp_serve(const tcp_serve &x);const tcp_serve &operator=(const tcp_serve &x);void Socket(){int fd = socket(AF_INET, SOCK_STREAM, 0); // 用IPv4协议家族,TCP协议if (-1 == fd){LOG(FATAL, "创建套接字失败");exit(1);} // 创建套接字失败_socket_fd = fd;LOG(INFO, "创建套接字成功");}void Bind(){struct sockaddr_in address;memset(&address, 0, sizeof(address)); // 把结构体初始化为0address.sin_family = AF_INET; // IPv4协议家族address.sin_addr.s_addr = INADDR_ANY; // 服务器选择任意IP地址接收请求address.sin_port = htons(_port); // 端口号信息,网络序列int opt = 1;if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt)) < 0){LOG(WARNING, "端口不能在短时间内连续绑定");} // 防止TIME_WAIT状态导致绑定端口失败LOG(INFO, "端口复用设置成功");if (-1 == bind(_socket_fd, (const struct sockaddr *)&address, (socklen_t)sizeof(address))){LOG(FATAL, "绑定套接字失败");exit(2); // 绑定套接字失败}LOG(INFO, "套接字绑定成功");}void Listen(){if (-1 == listen(_socket_fd, BACKLOG)){LOG(FATAL, "声明自己可连接失败");exit(3);} // 请求链接失败LOG(INFO, "套接字允许监听链接");}private:int _port; // 端口int _socket_fd; // 套接字文件描述符static tcp_serve *tcp_ptr;
};tcp_serve *tcp_serve::tcp_ptr = nullptr;
相关文章:
【C++】【网络】【Linux系统编程】单例模式,加锁封装TCP/IP协议套接字
目录 引言 获取套接字 绑定套接字 表明允许监听 单例模式设计 完整代码示例 个人主页:东洛的克莱斯韦克-CSDN博客 引言 有关套接字编程的细节和更多的系统调用课参考《UNIX环境高级编程》一书,可以在如下网站搜索电子版,该书在第16章详…...
Matplotlib在运维开发中的应用
在现代运维开发中,数据可视化扮演着越来越重要的角色。它能帮助我们更直观地理解系统状态,快速发现潜在问题,并辅助决策制定。Python的Matplotlib库作为一个强大而灵活的绘图工具,在运维领域有着广泛的应用。本文将探讨Matplotlib在运维开发中的常见应用场景,并提供实用的代码示…...
centos下nvme over rdma 环境配置
nvme over rdma 环境配置 本文主要介绍NVMe over RDMA的安装和配置。关于什么是NVMe over Fabrics,什么是NVMe over RDMA,本文就不做介绍了,网上资料一大堆。 可以看看什么是NVMe over Fabrics? RDMA(全称:Remote Dir…...
【C++】——多态详解
目录 1、什么是多态? 2、多态的定义及实现 2.1多态的构成条件 2.2多态语法细节处理 2.3协变 2.4析构函数的重写 2.5C11 override 和 final关键字 2.6重载—重写—隐藏的对比分析 3、纯虚函数和抽象类 4、多态的原理分析 4.1多态是如何实现的 4.2虚函数…...
STM32上实现FFT算法精准测量正弦波信号的幅值、频率和相位差(标准库)
在研究声音、电力或任何形式的波形时,我们常常需要穿过表面看本质。FFT(快速傅里叶变换)就是这样一种强大的工具,它能够揭示隐藏在复杂信号背后的频率成分。本文将带你走进FFT的世界,了解它是如何将时域信号转化为频域…...
计算机毕业设计 农场投入品运营管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
【笔记】2.1 半导体三极管(BJT,Bipolar Junction Transistor)
一、结构和符号 1. 三极管结构 常用的三极管的结构有硅平面管和锗合金管两种类型。各有PNP型和NPN型两种结构。 左图是NPN型硅平面三极管,右图是PNP型锗合金三极管。 从图中可见平面型三极管是先在一块大的金属板上注入杂质使之变成N型,然后再在中间注入杂质使之变成P型,…...
企业中文档团队的三种组织形式
大家好!今天咱们来聊聊企业里文档团队都是怎么组织的。 企业中,常见的文档团队组织形式有三种。 首先,最常见的就是集中式的文档团队。就是说,公司里头有几个不同的部门,每个部门都需要做文档。于是呢,公…...
古诗词四首鉴赏
1、出自蓟北门行 唐李白 虏阵横北荒,胡星曜精芒。 羽书速惊电,烽火昼连光。 虎竹救边急,戎车森已行。 明主不安席,按剑心飞扬。 推毂出猛将,连旗登战场。 兵威冲绝漠,杀气凌穹苍。…...
全国行政区划下载(高德、阿里、天地图)
一、网站链接: 阿里云数据可视化平台: DataV.GeoAtlas地理小工具系列 (aliyun.com) 链接: link 高德地图API获取行政区域: 高德地图API获取行政区域 (naivemap.com) 链接: link 天地图服务中心: 天地图 服务中心 (tianditu.g…...
Springboot提升-MapStruct组件使用
文章目录 1. 添加依赖2. 创建映射接口3. 在Spring Boot中使用MapStruct映射器4. 配置MapStruct 在Spring Boot项目中使用MapStruct可以帮助你更方便地管理对象之间的映射逻辑。下面是一些基本步骤来设置和使用MapStruct: 1. 添加依赖 首先,你需要在项目…...
如何借助ChatGPT提升论文质量:实战指南
在学术写作的过程中,非英语母语人士经常面临诸多挑战,尤其是当论文要提交给国际期刊时,语言规范和表达逻辑成为了必须克服的障碍。本文将通过实例详细解析如何利用ChatGPT来润色论文,使其达到发表级别的标准。 一、优秀学术论文的写作特点 要让学术论文在国际期刊上发表,…...
NLP开端:Tokenizer-文本向量化
Tokenizer 问题背景 An was a algorithm engineer 如上所示,在自然语言处理任务中,通常输入处理的数据是原始文本。但是算法模型自能处理数值类型,因此需要找到一种方法,将原始的文本数据转换为数值类型的数据。这就是分词器所…...
STM32 MCU学习资源
STM32 MCU学习资源 文档下载需要注册登录账号 ST公司官方文档 STM32 MCU开发者资源 STM32F446 相关PDF文档 ST中文论坛 中文译文资料 ST MCU中文官网 其他学习资源 野火STM32库开发实战指南 零基础快速上手STM32开发(手把手保姆级教程) 直接使…...
Python知识点:Python内存管理与优化
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! Python内存管理与优化指南 Python是一种动态类型的解释型语言,它提…...
SpringBoot Kafka发送消息与接收消息实例
前言 Kafka的基本工作原理 我们将消息的发布(publish)称作 producer(生产者),将消息的订阅(subscribe)表述为 consumer(消费者),将中间的存储阵列称作 broker(代理),这…...
【资料分析】刷题日记2
第一套 √ 2013-2016一共有13,14,15,16四年,亦即16 - 13 1 4年 √ 是多少倍 ③vs④:都是只给出了年均增速,③求的是其中一年的,无法确定;④求的是这个时段总共的,可…...
Aigtek功率放大器怎么选择型号
功率放大器在各个领域中都扮演着重要的角色,用于增强信号的幅度,以满足特定的需求。在选择功率放大器型号时,需要综合考虑多个因素,如应用领域、功率要求、频率范围、输入输出特性等。下面安泰电子官网将从这些方面详细介绍功率放…...
【RabbitMQ】重试机制、TTL
重试机制 在消息从Broker到消费者的传递过程中,可能会遇到各种问题,如网络故障、服务不可用、资源不足等,这些问题都可能导致消息处理失败。为了解决这些问题,RabbitMQ提供了重试机制,允许消息在处理失败之后重新发送…...
Linux用户及用户组操作命令笔记
1.用户概念及作用 用户:指的是Linux操作系统中用于管理系统或者服务的人 Linux下一切皆文件,所以用户管理的是相应的文件 基本上分为两种: 基本管理:文件的创建、删除、复制、查找、打包压缩等;文件的权限增加、减…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
