C语言:流量控制

前言

流量控制可以让发送端根据接收端的实际接受能力控制发送的数据量。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不会超过该大小的数据,该限制大小即为窗口大小,即窗口大小由接收端主机决定。如播放视频,音频文件时,需要对发送的数据进行流控。

mycat实现

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>#define BUF_SIZE    1024*1
#define BUF_SIZE    100
int main(int argc,char **argv)
{int fps,fpd=1;int ret;char buf[BUF_SIZE];int len,pos;if(argc <2){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}do{fps = open(argv[1],O_RDONLY);if(fps <0){if(errno != EINTR){perror("open");exit(1);}}}while(fps<0);while(1){len = read(fps,buf,BUF_SIZE);if(len < 0){if(errno == EINTR)continue;perror("read()");break;}if(len ==0)break;pos = 0;while(len > 0){ret = write(fpd,buf+pos,len);sleep(1);if(ret <0){if(errno == EINTR)continue;perror("write()");exit(1);}pos += ret;len-=ret;}}close(fps);return 0;
}

漏桶实现

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>#define CPS 100
#define BUF_SIZE    CPSstatic volatile int loop = 0;static void alrm_handler(int num)
{alarm(1);loop = 1;
}int main(int argc,char **argv)
{int fps,fpd=1;int ret;char buf[BUF_SIZE];int len,pos;if(argc <2){fprintf(stderr,"Usage:%s \n",argv[0]);exit(1);}signal(SIGALRM,alrm_handler);alarm(1);do{fps = open(argv[1],O_RDONLY);if(fps <0){if(errno != EINTR){perror("open");exit(1);}}}while(fps<0);while(1){//while(!loop);while(loop == 0)pause();   //用于等待一个打断的到来。不加则是忙等。loop = 0;while(1){len = read(fps,buf,BUF_SIZE);if(len < 0){if(errno == EINTR)continue;perror("read()");break;}break;}if(len ==0)break;pos = 0;while(len > 0){ret = write(fpd,buf+pos,len);if(ret <0){if(errno == EINTR)continue;perror("write()");exit(1);}pos += ret;len-=ret;}}close(fps);return 0;
}

如果读取的是打印机类的设备,并且当时打印机上面没有数据,那么程序就会一直循环于 read处

所以 漏桶的缺陷就是 如果没有数据的时候 就会一直循环等待,直到有数据,如果忽然来的数据量很大,也不能快速的去读数据,只能慢慢的一秒10个字节的去读n次

令牌桶实现

令牌桶的优势,就是 当没有数据可读的时候,会积攒自己的权限,意思是 如果之前30秒一直没有数据,读空了30秒,那么就存下30个权限,等到有数据的时候,快速使用前面30个权限,快速连续读30次。

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>#define CPS 10
#define BUF_SIZE    CPS
#define BURST 100static volatile sig_atomic_t  token  = 0; //信号原子类型,保证取值和赋值一定是一条指令去运行的static void alrm_handler(int num)
{alarm(1);token++;if(token >=  BURST)token =BURST;
}int main(int argc,char **argv)
{int fps,fpd=1;int ret;char buf[BUF_SIZE];int len,pos;if(argc <2){fprintf(stderr,"Usage:%s \n",argv[0]);exit(1);}signal(SIGALRM,alrm_handler);alarm(1);do{fps = open(argv[1],O_RDONLY);if(fps <0){if(errno != EINTR){perror("open");exit(1);}}}while(fps<0);while(1){while(token <= 0)pause();   //用于等待一个打断的到来。不加则是忙等。token--; // 操作不原子,可以出现--的时候出现++的情况while(1){len = read(fps,buf,BUF_SIZE);  //读的时候被信号打断时token会++if(len < 0){if(errno == EINTR)continue;perror("read()");break;}break;}if(len ==0)break;pos = 0;while(len > 0){ret = write(fpd,buf+pos,len);if(ret <0){if(errno == EINTR)continue;perror("write()");exit(1);}pos += ret;len-=ret;}}close(fps);return 0;
}

令牌桶实现封装

main.c

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "mytbf.h"#define CPS 10
#define BUF_SIZE    1024
#define BURST 100int main(int argc,char **argv)
{int fps,fpd=1;int ret;char buf[BUF_SIZE];int len,pos;if(argc <2){fprintf(stderr,"Usage:%s \n",argv[0]);exit(1);}mytbf_t* tbf;tbf = mytbf_init(CPS,BURST);if(tbf ==NULL){fprintf(stderr,"mytbf_init Error\n");exit(1);}do{fps = open(argv[1],O_RDONLY);if(fps <0){if(errno != EINTR){perror("open");exit(1);}}}while(fps<0);while(1){int size;size = mytbf_fetchtoken(tbf,BUF_SIZE);if(size <0){fprintf(stderr,"mytbf_fetchtoken:%s\n",strerror(-size));exit(1);}while(1){len = read(fps,buf,size);  //读的时候被信号打断时token会++if(len < 0){if(errno == EINTR)continue;perror("read()");break;}break;}if(len ==0)break;if(size -len > 0)   //如果读到的token数比取出来的token数小,就把没用到的token归还。{mytbf_returntoken(tbf,size -len);}pos = 0;while(len > 0){ret = write(fpd,buf+pos,len);if(ret <0){if(errno == EINTR)continue;perror("write()");exit(1);}pos += ret;len-=ret;}}close(fps);mytbf_destroy(tbf);return 0;
}

mytbf.h

#ifndef MYTBF_H
#define MYTBF_H#define MYTBF_MAX 1024typedef  void mytbf_t;mytbf_t* mytbf_init(int cps ,int burst);  //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*int mytbf_fetchtoken(mytbf_t*,int);  //获取tokenint mytbf_returntoken(mytbf_t*,int);  //返还tokenint mytbf_destroy(mytbf_t*);#endif

mytbf.c

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>#include "mytbf.h"struct mytbf_st
{int cps;int burst;int token;int pos;};
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;typedef void (*sighandler_t)(int);static sighandler_t alrm_handler_save;static int get_free_pos(void)
{for(int i=0;i< MYTBF_MAX;i++){if(job[i]==NULL)return i;}return -1;
}static void alrm_handler(int num)
{alarm(1);for(int i=0;i<MYTBF_MAX;i++){if(job[i] != NULL){job[i]->token += job[i]->cps;if(job[i]->token >job[i]->burst ){job[i]->token = job[i]->burst;}}}}static void module_unload()
{signal(SIGALRM,alrm_handler_save ); //关闭alarm注册的行为,还原之前的行为alarm(0); //关闭时钟信号for(int i=0;i<MYTBF_MAX;i++)free(job[i]);
}static void module_load()
{alrm_handler_save = signal(SIGALRM,alrm_handler); //定义新的行为,保存旧的行为alarm(1);atexit(module_unload);
}mytbf_t* mytbf_init(int cps ,int burst)  //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
{struct mytbf_st*me;int pos;if(inited == 0){module_load();inited = 1;}pos = get_free_pos();if(pos < 0)return NULL;me = malloc(sizeof(*me));if(me == NULL)return NULL;me->cps = cps;me->burst = burst;me->token = 0;me->pos = pos;job[pos] = me;return me;}
static int min(int token,int size)
{if(token> size)return size;return token;
}
int mytbf_fetchtoken(mytbf_t*ptr,int size)  //获取token
{if(size <= 0)return -EINVAL;  //参数非法struct mytbf_st*me = ptr;while(me->token <= 0 )  //token为空就等待pause();//  int n = min(me->token,size);int n = (me->token>size?size:me->token);me->token -= n;return n;
}int mytbf_returntoken(mytbf_t*ptr,int size)  //返还token
{if(size<=0)return -EINVAL;struct mytbf_st*me = ptr;me->token+= size;if(me->token > me->burst)me->token  = me->burst;return size;
}int mytbf_destroy(mytbf_t*ptr)
{struct mytbf_st *me;me = ptr;job[me->pos] = NULL;free(ptr);return 0;}

makefile

all:mytbf
CFLAGS=-g -Wall
mytbf:main.o mytbf.ogcc $^ $(CFLAGS) -o $@ clean:rm -rf *.o mytbf

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

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

相关文章

【Linux详解】进程的状态 | 运行 阻塞 挂起 | 僵尸和孤儿状态

目录 操作系统中 运行状态 阻塞状态 进程状态转换 Linux系统中 查看进程状态 深度睡眠状态 T 暂停状态 Z 僵尸状态 孤儿状态 文章手稿 xmind: 引言 介绍系统中的进程状态及其管理方式。将通过结合操作系统原理和实际代码示例&#xff0c;详细说明进程的各种状态、转换…

鸿蒙开发Ability Kit(程序框架服务):【FA模型切换Stage模型指导】 app和deviceConfig的切换

app和deviceConfig的切换 为了便于开发者维护应用级别的属性配置&#xff0c;Stage模型将config.json中的app和deviceConfig标签提取到了app.json5中进行配置&#xff0c;并对部分标签名称进行了修改&#xff0c;具体差异见下表。 表1 配置文件app标签差异对比 配置项FA模型…

Excel中的“点选输入”——次级下拉列表创建

在Excel中&#xff0c;用“数据验证”功能可以设置下拉列表&#xff0c;二级下拉列表需要设置公式。 (笔记模板由python脚本于2024年06月16日 18:36:37创建&#xff0c;本篇笔记适合经常使用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;http…

基于 Spring AOP 实现安全检查

在现代应用程序中&#xff0c;安全性是一个至关重要的方面。通过对系统中的关键操作进行安全检查&#xff0c;可以有效防止未授权的访问和操作。Spring AOP&#xff08;面向切面编程&#xff09;提供了一种优雅的方式来实现安全检查&#xff0c;而无需修改业务逻辑代码。本文将…

后端之路第三站(Mybatis)——入门配置

一、Mybatis是啥&#xff1f; 就是一个用java来操控数据库的框架语言 之前学的datagrip或者navicat这些软件里我们操作数据库&#xff0c;原理是我们编写完的操作语句发送到服务器传送到数据库系统&#xff0c;然后数据库执行完之后再发送给服务器返回给datagrip或者navicat显…

【linux/shell案例实战】shell界面命令快捷键

快捷键及含义&#xff1a; Ctrl&#xff0b;u剪切光标之前的内容。Ctul&#xff0b;k剪切光标之后的内容。Ctrl&#xff0b;e让光标移动到命令最前&#xff0c;Ctrl&#xff0b;a让光标移动到命令最后Ctrl&#xff0b;y 粘贴刚才所删除的内容。Ctrl&#xff0b;d 删除光标所在…

GPT-5:AI的博士时代与我们的未来

目录 引言第一部分&#xff1a;GPT-5技术突破预测1. NLP技术的革新1.1 算法进步对理解力提升的影响1.2 技术突破推动行业发展 2. 行业推动力2.1 教育行业的变革2.2 医疗行业的创新2.3 法律行业的效率提升 第二部分&#xff1a;智能系统与人类的协作1. 辅助决策的角色1.1 决策支…

游戏AI的创造思路-技术基础-sigmoid函数详解

在前面的机器学习和深度学习的内容中&#xff0c;大量出现了sigmoid函数&#xff0c;所以本篇为大家介绍下sigmoid函数&#xff0c;希望对大家理解前面的算法和后面的Transformer有所帮助 目录 3.8. sigmoid函数 3.8.1. 定义 3.8.2. 性质 3.8.3. 应用 3.8.4. 缺点 3.8.5.…

Flutter实现页面间传参

带参跳转 步骤 在router中配置这个路由需要携带的参数,这里的参数是 arguments,注意要用花括号包裹参数名称 在相应组件中实现带参构造函数 在state类中可以直接使用${widget.arguments}来访问到传递的参数 在其他页面中使用Navigator.pushNamed()带参跳转

【昇思初学入门】第八天打卡-模型保存与加载

模型保存与加载 学习心得 保存 CheckPoint 格式文件&#xff0c;在模型训练过程中&#xff0c;可以添加检查点(CheckPoint)用于保存模型的参数&#xff0c;以便进行推理及再训练使用。如果想继续在不同硬件平台上做推理&#xff0c;可通过网络和CheckPoint格式文件生成对应的…

C++中常用的标志库

标准库 C标准库是一个强大的工具集&#xff0c;它包含了一组丰富的类和函数&#xff0c;可以帮助开发者进行各种操作&#xff0c;如输入输出、字符串操作、数据结构管理、算法实现等。以下是一些常用的C标准库及其使用方法。 1. 输入输出库 <iostream> 用于标准输入输…

2024年最新通信安全员考试题库

61.架设架空光缆&#xff0c;可使用吊板作业的情况是&#xff08;&#xff09;。 A.在2.2/7规格的电杆与墙壁之间的吊线上&#xff0c;吊线高度5m B.在2.2/7规格的墙壁与墙壁之间的吊线上&#xff0c;吊线高度6m C.在2.2/7规格的电杆与电杆之间的吊线上&#xff0c;吊线高度…

[leetcode]24-game

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:static constexpr int TARGET 24;static constexpr double EPSILON 1e-6;static constexpr int ADD 0, MULTIPLY 1, SUBTRACT 2, DIVIDE 3;bool judgePoint24(vector<int> &nums) {vector&l…

【C++LeetCode】【热题100】三数之和【中等】-不同效率的题解【6】

题目&#xff1a; 暴力方法&#xff1a; class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> res;std::unordered_set<std::string> uniqueValues;//保证结果唯一for(int i0;i<n…

工商业储能柜用的Acrel-2000ES储能能量管理系统-安科瑞 蒋静

概述 Acrel-2000ES储能能量管理系统&#xff0c;专门针对工商业储能柜、储能集装箱研发的一款储能EMS&#xff0c;具有完善的储能监控与管理功能,涵盖了储能系统设备(PCS、BMS、电表、消防、空调等)的详细信息&#xff0c;实现了数据采集、数据处理、数据存储、数据查询与分析…

PHP米表域名出售管理源码带后台

源码介绍 html5米表源码PHP域名销售程序安装方法&#xff1a; 本站已测试,各项功能正常,功能易用,不复杂,非常适合个人米表使用 1、所有文件传至网站目录 2、浏览器执行http://你的访问网址/install 3、输入mysql帐号及密码信息&#xff0c;提交安装 源码截图 源码下载 …

MySQL程序使用的选项文件

MySQL程序使用的选项文件如下&#xff1a; 显示帮助消息并退出。 在具有多个网络接口的计算机上&#xff0c;使用此选项可以选择用于连接MySQL服务器的接口。 安装字符集的目录。 如果可能&#xff0c;压缩客户端和服务器之间发送的所有信息。 从MySQL 8.0.18开始&#xff0c;…

GPOPS-II教程(3): 航天器最优控制问题

文章目录 问题描述GPOPS代码main functioncontinuous functionendpoint function完整代码代码仿真结果 最后 问题描述 例子出自论文 Direct solution of nonlinear optimal control problems using quasilinearization and Chebyshev polynomials&#xff08;DOI&#xff1a;1…

新手选择代理IP时这几点误区一定要避开!

在选择代理IP时&#xff0c;许多用户可能会因为对代理IP的认识不足或受到一些误导&#xff0c;而陷入一些常见的误区。这些误区不仅可能导致用户无法达到预期的效果&#xff0c;还可能带来一些不必要的风险。下面&#xff0c;IPIDEA代理IP就与大家一同分析在选择代理IP时需要避…

国企:2024年6月中国铁路相关招聘信息,6.27截止

中国铁路济南局集团有限公司2024年度 招聘普通高校本科及以上学历毕业生公告(三) 中国铁路济南局集团有限公司根据企业发展需要,拟招聘普通高等院校本科及以上学历毕业生,现将有关事项公告如下: 一、招聘计划 本次招聘岗位均为生产一线操作技能岗位,具体岗位、专业要求…