c++学习笔记(47)
七、_public.cpp
#include "_public.h"
// 如果信号量已存在,获取信号量;如果信号量不存在,则创建它并初始化为 value。
// 如果用于互斥锁,value 填 1,sem_flg 填 SEM_UNDO。
// 如果用于生产消费者模型,value 填 0,sem_flg 填 0。
bool csemp::init(key_t key,unsigned short value,short sem_flg)
{
if (m_semid!=-1) return false; // 如果已经初始化了,不必再次初始化。
m_sem_flg=sem_flg;
// 信号量的初始化不能直接用 semget(key,1,0666|IPC_CREAT)
// 因为信号量创建后,初始值是 0,如果用于互斥锁,需要把它的初始值设置为 1,
// 而获取信号量则不需要设置初始值,所以,创建信号量和获取信号量的流程不同。
// 信号量的初始化分三个步骤:
// 1)获取信号量,如果成功,函数返回。
// 2)如果失败,则创建信号量。
// 3) 设置信号量的初始值。
// 获取信号量。
if ( (m_semid=semget(key,1,0666)) == -1)
{
// 如果信号量不存在,创建它。
if (errno==ENOENT)
{
// 用 IPC_EXCL 标志确保只有一个进程创建并初始化信号量,其它进程只能获取。
if ( (m_semid=semget(key,1,0666|IPC_CREAT|IPC_EXCL)) == -1)
{
if (errno==EEXIST) // 如果错误代码是信号量已存在,则再次获取信号量。
{
if ( (m_semid=semget(key,1,0666)) == -1)
{
perror("init 1 semget()"); return false;
}
return true;
}
else // 如果是其它错误,返回失败。
{
perror("init 2 semget()"); return false;
}
}
// 信号量创建成功后,还需要把它初始化成 value。
union semun sem_union;
sem_union.val = value; // 设置信号量的初始值。
if (semctl(m_semid,0,SETVAL,sem_union) < 0)
{
perror("init semctl()"); return false;
}
}
else
{ perror("init 3 semget()"); return false; }
}
return true;
}
// 信号量的 P 操作(把信号量的值减 value),如果信号量的值是 0,将阻塞等待,直到信号量的值
大于 0。
bool csemp::wait(short value)
{
if (m_semid==-1) return false;
struct sembuf sem_b;
sem_b.sem_num = 0; // 信号量编号,0 代表第一个信号量。
sem_b.sem_op = value; // P 操作的 value 必须小于 0。
sem_b.sem_flg = m_sem_flg;
if (semop(m_semid,&sem_b,1) == -1) { perror("p semop()"); return false; }
return true;
}
// 信号量的 V 操作(把信号量的值减 value)。
bool csemp::post(short value)
{
if (m_semid==-1) return false;
struct sembuf sem_b;
sem_b.sem_num = 0; // 信号量编号,0 代表第一个信号量。
sem_b.sem_op = value; // V 操作的 value 必须大于 0。
sem_b.sem_flg = m_sem_flg;
if (semop(m_semid,&sem_b,1) == -1) { perror("V semop()"); return false; }
return true;
}
// 获取信号量的值,成功返回信号量的值,失败返回-1。
int csemp::getvalue()
{
return semctl(m_semid,0,GETVAL);
}
// 销毁信号量。
bool csemp::destroy()
{
if (m_semid==-1) return false;
if (semctl(m_semid,0,IPC_RMID) == -1) { perror("destroy semctl()"); return false; }
return true;
}
csemp::~csemp()
{
}
八、makefile
all:demo1 demo2 demo3 incache outcache
demo1:demo1.cpp _public.h _public.cpp
g++ -g -o demo1 demo1.cpp _public.cpp
demo2:demo2.cpp _public.h _public.cpp
g++ -g -o demo2 demo2.cpp _public.cpp
demo3:demo3.cpp _public.h _public.cpp
g++ -g -o demo3 demo3.cpp _public.cpp
incache:incache.cpp _public.h _public.cpp
g++ -g -o incache incache.cpp _public.cpp
outcache:outcache.cpp _public.h _public.cpp
g++ -g -o outcache outcache.cpp _public.cpp
clean:
rm -f demo1 demo2 demo3 incache outcache
340、第一个网络通讯程序
一、网络通讯的流程
二、demo1.cpp
/*
* 程序名:demo1.cpp,此程序用于演示 socket 的客户端
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
int main(int argc,char *argv[])
{
if (argc!=3)
{
cout << "Using:./demo1 服务端的 IP 服务端的端口\nExample:./demo1 192.168.101.139
5005\n\n";
return -1;
}
// 第 1 步:创建客户端的 socket。
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd==-1)
{
perror("socket"); return -1;
}
// 第 2 步:向服务器发起连接请求。
struct hostent* h; // 用于存放服务端 IP 的结构体。
if ( (h = gethostbyname(argv[1])) == 0 ) // 把字符串格式的 IP 转换成结构体。
{
cout << "gethostbyname failed.\n" << endl; close(sockfd); return -1;
}
struct sockaddr_in servaddr; // 用于存放服务端 IP 和端口的结构体。
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // 指定服务端的 IP 地址。
servaddr.sin_port = htons(atoi(argv[2])); // 指定服务端的通信端口。
if (connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))!=0) // 向服务端发起连
接清求。
{
perror("connect"); close(sockfd); return -1;
}
// 第 3 步:与服务端通讯,客户发送一个请求报文后等待服务端的回复,收到回复后,再发下一
个请求报文。
char buffer[1024];
for (int ii=0;ii<3;ii++) // 循环 3 次,将与服务端进行三次通讯。
{
int iret;
memset(buffer,0,sizeof(buffer));
sprintf(buffer,"这是第%d 个超级女生,编号%03d。",ii+1,ii+1); // 生成请求报文内容。
// 向服务端发送请求报文。
if ( (iret=send(sockfd,buffer,strlen(buffer),0))<=0)
{
perror("send"); break;
}
cout << "发送:" << buffer << endl;
memset(buffer,0,sizeof(buffer));
// 接收服务端的回应报文,如果服务端没有发送回应报文,recv()函数将阻塞等待。
if ( (iret=recv(sockfd,buffer,sizeof(buffer),0))<=0)
{
cout << "iret=" << iret << endl; break;
}
cout << "接收:" << buffer << endl;
sleep(1);
}
// 第 4 步:关闭 socket,释放资源。
close(sockfd);
}
三、demo2.cpp
/*
* 程序名:demo2.cpp,此程序用于演示 socket 通信的服务端
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
int main(int argc,char *argv[])
{
if (argc!=2)
{
cout << "Using:./demo2 通讯端口\nExample:./demo2 5005\n\n"; // 端口大于 1024,
不与其它的重复。
cout << "注意:运行服务端程序的 Linux 系统的防火墙必须要开通 5005 端口。\n";
cout << " 如果是云服务器,还要开通云平台的访问策略。\n\n";
return -1;
}
// 第 1 步:创建服务端的 socket。
int listenfd = socket(AF_INET,SOCK_STREAM,0);
if (listenfd==-1)
{
perror("socket"); return -1;
}
// 第 2 步:把服务端用于通信的 IP 和端口绑定到 socket 上。
struct sockaddr_in servaddr; // 用于存放服务端 IP 和端口的数据结构。
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; // 指定协议。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端任意网卡的 IP 都可以用于通讯。
servaddr.sin_port = htons(atoi(argv[1])); // 指定通信端口,普通用户只能用 1024 以上的
端口。
// 绑定服务端的 IP 和端口。
if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
{
perror("bind"); close(listenfd); return -1;
}
// 第 3 步:把 socket 设置为可连接(监听)的状态。
if (listen(listenfd,5) != 0 )
{
perror("listen"); close(listenfd); return -1;
}
// 第 4 步:受理客户端的连接请求,如果没有客户端连上来,accept()函数将阻塞等待。
int clientfd=accept(listenfd,0,0);
if (clientfd==-1)
{
perror("accept"); close(listenfd); return -1;
}
cout << "客户端已连接。\n";
// 第 5 步:与客户端通信,接收客户端发过来的报文后,回复 ok。
char buffer[1024];
while (true)
{
int iret;
memset(buffer,0,sizeof(buffer));
// 接收客户端的请求报文,如果客户端没有发送请求报文,recv()函数将阻塞等待。
// 如果客户端已断开连接,recv()函数将返回 0。
if ( (iret=recv(clientfd,buffer,sizeof(buffer),0))<=0)
{
cout << "iret=" << iret << endl; break;
}
cout << "接收:" << buffer << endl;
strcpy(buffer,"ok"); // 生成回应报文内容。
// 向客户端发送回应报文。
if ( (iret=send(clientfd,buffer,strlen(buffer),0))<=0)
{
perror("send"); break;
}
cout << "发送:" << buffer << endl;
}
// 第 6 步:关闭 socket,释放资源。
close(listenfd); // 关闭服务端用于监听的 socket。
close(clientfd); // 关闭客户端连上来的 socket。
}
相关文章:
c++学习笔记(47)
七、_public.cpp #include "_public.h" // 如果信号量已存在,获取信号量;如果信号量不存在,则创建它并初始化为 value。 // 如果用于互斥锁,value 填 1,sem_flg 填 SEM_UNDO。 // 如果用于生产消费者模型&am…...

软件设计之SSM(1)
软件设计之SSM(1) 路线图推荐: 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷新版SSM框架全套视频教程,Spring6SpringBoot3最新SSM企业级开发 资料可以去尚硅谷官网免费领取 学习内容: Spring框架结构SpringIoC容器SpringIoC实践…...
STM32F745IE 能进定时器中断,无法进主循环
当你遇到STM32F745IE这类问题,即能够进入定时器中断但无法进入主循环(main() 函数中的循环),可能的原因和解决方法包括以下几个方面: 检查中断优先级和嵌套: 确保没有其他更高优先级的中断持续运行并阻止了主循环的执行。使用调试工具查看中断的进入和退出情况。检查中断…...

《凡人歌》中的IT职业启示录
《凡人歌》是由中央电视台、正午阳光、爱奇艺出品,简川訸执导,纪静蓉编剧,侯鸿亮任制片,殷桃、王骁领衔主演,章若楠、秦俊杰、张哲华、陈昊宇主演的都市话题剧 ,改编自纪静蓉的小说《我不是废柴》。该剧于2…...

go libreoffice word 转pdf
一、main.go 关键代码 完整代码 package mainimport ("fmt""github.com/jmoiron/sqlx""github.com/tealeg/xlsx""log""os/exec""path/filepath" ) import _ "github.com/go-sql-driver/mysql"import &q…...
打造双模兼容npm包:无缝支持require与import
为了实现一个npm包同时支持require和import,你需要确保你的包同时提供了CommonJS和ES6模块的入口点。这通常是通过在package.json文件中指定main和module字段来实现的,以及在构建过程中生成两种不同模块格式的文件。 以下是具体步骤: 设置pa…...
便捷将屏幕投射到安卓/iOS设备-屏幕投射到安卓/iOS设备,Windows/Mac电脑或智能电视上-供大家学习研究参考
1. 下载并安装软件(安卓苹果都需要) 确保 Android 设备和 Windows/Mac电脑都安装。启动应用程序并将 Android 设备和 Windows / Mac 了解到同一个wifi下面。 2、 发起投屏请求 在接收设备上:...

yolox训练自己的数据集
环境搭建 gpu按自己情况安装 nvidia-smi 查看自己的版本 CUDA和cudnn 按自己的安装,我的驱动551.76,注意不要用最新的,官网只要求驱动是大于等于,可以用低版本的cuda,我安装的是CUDA 11.1 cuda下载后,…...

Centos8.5.2111(1)之本地yum源搭建和docker部署与网络配置
由于后边可能要启动多个服务,避免服务之间相互干扰,本课程建议每个服务独立部署到一台主机上,这样做会导致资源占用过多,可能会影响系统的运行。服务器部署一般不采用GUI图形界面部署,而是采用命令行方式部署ÿ…...

基于SSM+小程序的自习室选座与门禁管理系统(自习室1)(源码+sql脚本+视频导入教程+文档)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 1、管理员实现了首页、基础数据管理、论坛管理、公告信息管理、用户管理、座位管理等 2、用户实现了在论坛模块通过发帖与评论帖子的方式进行信息讨论,也能对账户进行在线充值…...

支付宝远程收款api之小荷包跳转码
想要生成小荷包跳转码的二维码,需要进行以下步骤: 1、开通支付宝小荷包的收款功能权限 2、获取支付宝的小荷包收款码和支付宝账户的UID已经手机号等相应信息(可能会有变动) 3、可能需要一定的代码基础,讲所需信息填…...

STM32 F1移植FATFS文件系统 USMART组件测试相关函数功能
STM32 F1移植FATFS文件系统 使用USMART调试组件测试相关函数功能 文章目录 STM32 F1移植FATFS文件系统 使用USMART调试组件测试相关函数功能前言部分主要相关代码# USMART介绍1. mf_scan_files 扫描磁盘文件2. mf_mount 挂载磁盘3. mf_open 打开文件4. mf_read 读数据内容5. mf…...

YOLOv8改进 | 融合篇,YOLOv8主干网络替换为MobileNetV3+CA注意机制+添加小目标检测层(全网独家首发,实现极限涨点)
原始 YOLOv8 训练结果: YOLOv8 + MobileNetV3改进后训练结果: YOLOv8 + MobileNetV3 + CA 注意机制 + 添加小目标检测层改进后训练结果(极限涨点): 摘要 小目标检测难点众多,导致很多算法对小目标的检测效果远不如大中型目标。影响算法性能的主要原因如下:第一,小目…...

深入探索机器学习中的目标分类算法
在当今数据驱动的世界中,机器学习(Machine Learning, ML)正逐渐成为解决问题的重要工具。在众多机器学习任务中,目标分类(Classification)算法尤其受到关注。本文将深入探讨目标分类算法的基本概念、常见类…...

一文上手SpringSecurity【七】
之前我们在测试的时候,都是使用的字符串充当用户名称和密码,本篇将其换成MySQL数据库. 一、替换为真实的MySQL 1.1 引入依赖 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</v…...

深圳龙链科技:全球区块链开发先锋,领航Web3生态未来
【深圳龙链科技】是全球领先的Web3区块链技术开发公司,专注于为全球客户提供创新高效的区块链解决方案。 深圳龙链科技由币安资深股东携手香港领先的Web3创新枢纽Cyberport联袂打造,立足于香港这一国际金融中心,放眼全球,汇聚了华…...

手写代码,利用 mnist 数据集测试对比 kan 和 cnn/mlp 的效果
你好呀,我是董董灿。 kan 模型火了一段时间,很多人从理论的角度给出了非常专业的解读,基本结论是:从目前来看,kan 很难替代 mlp 成为一个更加经典的模型结构。 我这里就不从理论方面进行回答了,直接给出一…...

基于Java+SQL Server2008开发的(CS界面)个人财物管理系统
一、需求分析 个人财务管理系统是智能化简单化个人管理的重要的组成部分。并且随着计算机技术的飞速发展,计算机在管理方面应用的旁及,利用计算机来实现个人财务管理势在必行。本文首先介绍了个人财务管理系统的开发目的,其次对个人财务管理…...

15年408计算机网络
第一题: 解析: 接收方使用POP3向邮件服务器读取邮件,使用的TCP连接,TCP向上层提供的是面向连接的,可靠的数据传输服务。 第二题: 解析:物理层-不归零编码和曼彻斯特编码 编码1:电平在…...
C++ const关键字
const 1. 修饰变量(包括函数参数 函数返回值) const int v0 10; v0 0; // error 不能修改const修饰的变量 2. 修饰指针 int v1 10; int v2 20; int v3 30; 2.1 常量指针 const 在指针左边,左定值,即不能通过指针修改该…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...