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.pswp.cn/diannao/35823.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/35823.shtml
英文地址,請注明出處:http://en.pswp.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年度 招聘普通高校本科及以上學歷畢業生公告(三) 中國鐵路濟南局集團有限公司根據企業發展需要,擬招聘普通高等院校本科及以上學歷畢業生,現將有關事項公告如下: 一、招聘計劃 本次招聘崗位均為生產一線操作技能崗位,具體崗位、專業要求…