当前位置: 首页 > 编程日记 > 正文

类似ngnix的多进程监听用例

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

多进程监听适合于短连接,且连接间无交集的应用。
前两天简单写了一个,在这里保存一下。

  1. #include <sys/types.h>

  2. #include <stdarg.h>

  3. #include <signal.h>

  4. #include <unistd.h>

  5. #include <fcntl.h>

  6. #include <time.h>

  7. #include <string.h>

  8. #include <stdlib.h>

  9. #include <stdio.h>

  10. #include <errno.h>

  11. #include <sys/socket.h>  

  12. #include <arpa/inet.h>


  13. char * ToDateStr(time_t tt, char *szDateTime, const char *szFormat)

  14. {

  15. size_t i, len;

  16. char field[3], c1 = ' ', c2 = '-', c3 = ':', c4 = '/'; /* 常见的分隔符 */

  17. char *p;

  18. struct tm result;


  19. if (szDateTime == NULL)

  20. {

  21. return NULL;

  22. }


  23. localtime_r(&tt, &result);


  24. /* 默认的格式 yyyy-mm-dd hh:mi:ss*/

  25. if (szFormat == NULL)

  26. {

  27. sprintf(szDateTime, "%04d-%02d-%02d %02d:%02d:%02d", 

  28. result.tm_year + 1900, result.tm_mon + 1, result.tm_mday,

  29. result.tm_hour, result.tm_min, result.tm_sec);


  30. szDateTime[strlen("yyyy-mm-dd hh:mi:ss")] = '\0';

  31. return szDateTime;

  32. }


  33. /* 用户指定格式 */

  34. len = strlen(szFormat);

  35. i = 0;

  36. p = szDateTime;


  37. /* 判断前4个字符是否为yyyy */

  38. if (strncmp(szFormat, "yyyy", 4) == 0) 

  39. {

  40. sprintf(p, "%04d", result.tm_year + 1900);

  41. p += 4;

  42. i += 4;

  43. }


  44. /* 格式中的剩余部分 */

  45. while (i < len)

  46. {

  47. /* 格式中的每个域必须以两个紧邻字符为整体 */

  48. field[0] = szFormat[i];

  49. i += 1;


  50. if (field[0] != c1 && field[0] != c2 && field[0] != c3 && field[0] != c4) /* 如果第一个字符不是分隔符 */

  51. {

  52. field[1] = szFormat[i];

  53. field[2] = '\0';

  54. i += 1;


  55. if (strcmp(field, "yy") == 0) /* 这种情况下整个格式里最多有两个yy */

  56. {

  57. sprintf(p, "%02d", (result.tm_year + 1900) % 100);

  58. }

  59. else if (strcmp(field, "mm") == 0)

  60. {

  61. sprintf(p, "%02d", result.tm_mon + 1);

  62. }

  63. else if (strcmp(field, "dd") == 0)

  64. {

  65. sprintf(p, "%02d", result.tm_mday);

  66. }

  67. else if (strcmp(field, "hh") == 0)

  68. {

  69. sprintf(p, "%02d", result.tm_hour);

  70. }

  71. else if (strcmp(field, "mi") == 0)

  72. {

  73. sprintf(p, "%02d", result.tm_min);

  74. }

  75. else if (strcmp(field, "ss") == 0)

  76. {

  77. sprintf(p, "%02d", result.tm_sec);

  78. }

  79. else

  80. {

  81. return NULL;

  82. }


  83. p += 2;

  84. }

  85. else /* 如果是分隔符则直接打印出来 */

  86. {

  87. *p = field[0];

  88. p += 1;

  89. }

  90. }


  91. *p = '\0';


  92. return szDateTime;

  93. }


  94. //时间格式化

  95. char * Now(char *szDateTime, const char *szFormat)

  96. {

  97. return ToDateStr(time(NULL), szDateTime, szFormat);

  98. }


  99. //写日志文件

  100. void mlog(char *logFileName,char *fmt,...)

  101. {

  102. char        log_path[128];

  103. char        date_time[20];

  104. char        date_str[10];

  105. char        time_str[10];


  106. FILE         *fp;

  107. va_list        varArg;

  108. char        buf_str[1024];


  109. memset(log_path,  0, sizeof(log_path));

  110. memset(date_time, 0, sizeof(date_time));

  111. memset(date_str,  0, sizeof(date_str));

  112. memset(time_str,  0, sizeof(time_str));

  113. memset(buf_str,   0, sizeof(buf_str));


  114. // 取日期及时间

  115. Now(date_time, "yyyymmddhh:mi:ss");

  116. memcpy(date_str, date_time, 8);

  117. memcpy(time_str, date_time + 8, 8);


  118. /* 组合日志文件目录 */

  119. sprintf(log_path, "./%s.%s", logFileName, date_str);


  120. /* 以(创建)追加方式打开日志文件 */ 

  121. fp = fopen(log_path, "a+");

  122. if(fp == NULL)

  123. {

  124. return;

  125. }


  126. va_start(varArg, fmt);

  127. vsprintf(buf_str, fmt, varArg);

  128. va_end(varArg);


  129. fprintf(fp, "%s: %s\n", time_str, buf_str);        


  130. fclose(fp);

  131. }


  132. //写独占文件锁

  133. int AcquireWriteLock(int fd, int start, int len)

  134. {

  135. struct flock arg;

  136. arg.l_type = F_WRLCK; // 加写锁

  137. arg.l_whence = SEEK_SET;

  138. arg.l_start = start;

  139. arg.l_len = len;

  140. arg.l_pid = getpid();


  141. return fcntl(fd, F_SETLKW, &arg);

  142. }


  143. //释放独占文件锁

  144. int ReleaseLock(int fd, int start, int len)

  145. {

  146. struct flock arg;

  147. arg.l_type = F_UNLCK; //  解锁

  148. arg.l_whence = SEEK_SET;

  149. arg.l_start = start;

  150. arg.l_len = len;

  151. arg.l_pid = getpid();


  152. return fcntl(fd, F_SETLKW, &arg);

  153. }


  154. //查看写锁

  155. int SeeLock(int fd, int start, int len)

  156. {

  157. struct flock arg;

  158. arg.l_type = F_WRLCK;

  159. arg.l_whence = SEEK_SET;

  160. arg.l_start = start;

  161. arg.l_len = len;

  162. arg.l_pid = getpid();


  163. if (fcntl(fd, F_GETLK, &arg) != 0) // 获取锁

  164. {

  165. return -1; // 测试失败

  166. }


  167. if (arg.l_type == F_UNLCK)

  168. {

  169. return 0; // 无锁

  170. }

  171. else if (arg.l_type == F_RDLCK)

  172. {

  173. return 1; // 读锁

  174. }

  175. else if (arg.l_type == F_WRLCK)

  176. {

  177. return 2; // 写所

  178. }


  179. return 0;

  180. }


  181. int Chlid_Run(int nServerfd)

  182. {

  183. socklen_t nClientAddrSize = 0;

  184. int nClientfd       = -1;

  185. struct sockaddr_in Clientaddr;


  186. //循环监听接收数据

  187. while(1)  

  188. {  

  189. nClientAddrSize = sizeof(struct sockaddr_in);


  190. nClientfd = accept(nServerfd, (struct sockaddr *)(&Clientaddr), &nClientAddrSize);

  191. if(-1 == nClientfd)  

  192. {  

  193. printf("[Chlid_Run]accept fail !\n");  

  194. return -1;

  195. }


  196. //随便返回一个数据

  197. char szReturn[20];

  198. sprintf(szReturn, "hello");

  199. if(-1 == write(nClientfd, szReturn, strlen(szReturn)))  

  200. {

  201. mlog((char* )"process", (char* )"[Chlid_Run](%s:%d)(%d)Connected Send error!", inet_ntoa(Clientaddr.sin_addr), ntohs(Clientaddr.sin_port), getpid());  

  202. return -1;  

  203. }


  204. //打印进程ID

  205. mlog((char* )"process", (char* )"[Chlid_Run](%s:%d)Connected pid=%d!", inet_ntoa(Clientaddr.sin_addr), ntohs(Clientaddr.sin_port), getpid());  


  206. //关闭socket连接

  207. close(nClientfd);

  208. }

  209. }


  210. int main(int argc, char *argv[])

  211. {

  212. //当前监控子线程个数

  213. int nNumChlid = 5;


  214. //检测时间间隔参数

  215. struct timespec tsRqt;


  216. //文件锁

  217. int fd_lock = 0;


  218. //要监听的IP和端口

  219. struct sockaddr_in server_addr;

  220. struct sockaddr_in client_addr;

  221. int nPort = 10030;    //监听端口

  222. int nServerfd = 0;    //Server Socket


  223. int nRet = 0;


  224. //主进程检测时间间隔(设置每隔5秒一次)

  225. tsRqt.tv_sec  = 5;

  226. tsRqt.tv_nsec = 0;


  227. // 打开(创建)锁文件

  228. char szFileName[200] = {'\0'};

  229. memset(szFileName, 0, sizeof(flock));

  230. sprintf(szFileName, "./MultiListen.lk", getenv("HOME"));

  231. fd_lock = open(szFileName, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

  232. if (fd_lock < 0)

  233. {

  234. printf("open the flock and exit, errno = %d.", errno);

  235. exit(1);

  236. }


  237. //查看当前文件锁是否已锁

  238. nRet = SeeLock(fd_lock, 0, sizeof(int));

  239. if (nRet == -1 || nRet == 2) 

  240. {

  241. printf("file is already exist!");

  242. exit(1);

  243. }


  244. //如果文件锁没锁,则锁住当前文件锁

  245. if (AcquireWriteLock(fd_lock, 0, sizeof(int)) != 0)

  246. {

  247. printf("lock the file failure and exit, idx = 0!.");

  248. exit(1);

  249. }


  250. //写入子进程锁信息

  251. lseek(fd_lock, 0, SEEK_SET);

  252. for (int nIndex = 0; nIndex <= nNumChlid; nIndex++)

  253. {

  254. write(fd_lock, &nIndex, sizeof(nIndex));

  255. }


  256. //在这里初始化监听

  257. nServerfd = socket(AF_INET, SOCK_STREAM, 0);

  258. if(-1 == nServerfd)

  259. {

  260. printf("[Main]Create Server FD error.\n");

  261. return -1;

  262. }


  263. //初始化监听地址信息

  264. bzero(&server_addr,sizeof(struct sockaddr_in));  

  265. server_addr.sin_family=AF_INET;  

  266. server_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */  

  267. server_addr.sin_port=htons(nPort); 


  268. //绑定Socket FD

  269. if(-1 == bind(nServerfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))  

  270. {  

  271. printf("[main]bind server addr fail!\n");  

  272. return -1;  

  273. }


  274. //开始监听

  275. if(-1 == listen(nServerfd, 5))  

  276. {  

  277. printf("[main]listen server fail!\r\n");  

  278. return -1;  

  279. }




  280. while (1)

  281. {

  282. for (int nChlidIndex = 1; nChlidIndex <= nNumChlid; nChlidIndex++)

  283. {

  284. //测试每个子进程的锁是否还存在

  285. nRet = SeeLock(fd_lock, nChlidIndex * sizeof(int), sizeof(int));

  286. if (nRet == -1 || nRet == 2)

  287. {

  288. continue;

  289. }

  290. //如果文件锁没有被锁,则设置文件锁,并启动子进程

  291. int npid = fork();

  292. if (npid == 0)

  293. {

  294. //上文件锁

  295. if(AcquireWriteLock(fd_lock, nChlidIndex * sizeof(int), sizeof(int)) != 0)

  296. {

  297. printf("child %d AcquireWriteLock failure.\n", nChlidIndex);

  298. exit(1);

  299. }


  300. //启动子进程

  301. Chlid_Run(nServerfd);


  302. //子进程在执行完任务后必须退出循环和释放锁 

  303. //ReleaseLock(fd_lock, nChlidIndex * sizeof(int), sizeof(int));                

  304. }

  305. }


  306. printf("child count(%d) is ok.\n", nNumChlid);

  307. //检查间隔

  308. nanosleep(&tsRqt, NULL);

  309. }


  310. return 0;

  311. }


复制代码



转载于:https://my.oschina.net/u/2273582/blog/346311

相关文章:

今日头条李磊等最新论文:用于文本生成的核化贝叶斯Softmax

译者 | Raku 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;摘要用于文本生成的神经模型需要在解码阶段具有适当词嵌入的softmax层&#xff0c;大多数现有方法采用每个单词单点嵌入的方式&#xff0c;但是一个单词可能具有多种意义&#xff0c;在不同的背景下&#…

FFmpeg中RTSP客户端拉流测试代码

之前在https://blog.csdn.net/fengbingchun/article/details/91355410中给出了通过LIVE555实现拉流的测试代码&#xff0c;这里通过FFmpeg来实现&#xff0c;代码量远小于LIVE555&#xff0c;实现模块在libavformat。 在4.0及以上版本中&#xff0c;FFmpeg有了些变动&#xff…

虚拟机下运行linux通过nat模式与主机通信、与外网连接

首先&#xff1a;打开虚拟机的编辑菜单下的虚拟网络编辑器&#xff0c;选中VMnet8 NAT模式。通过NAT设置获取网关IP&#xff0c;通过DHCP获取可配置的IP区间。同时&#xff0c;将虚拟机的虚拟机菜单的设置选项中的网络适配器改为NAT模式。即可&#xff01; 打开linux&#xff0…

远程过程调用RPC简介

RPC(Remote Procedure Call, 远程过程调用)&#xff1a;是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 RPC是一种技术思想而非一种规范或协议&#xff0c;常见RPC技术和框架有&#xff1a; (1). 应用级的服务框架&#xff1a;阿里的…

iOS开发:沙盒机制以及利用沙盒存储字符串、数组、字典等数据

iOS开发&#xff1a;沙盒机制以及利用沙盒存储字符串、数组、字典等数据 1、初识沙盒&#xff1a;(1)、存储在内存中的数据&#xff0c;程序关闭&#xff0c;内存释放&#xff0c;数据就会丢失&#xff0c;这种数据是临时的。要想数据永久保存&#xff0c;将数据保存成文件&am…

支撑亿级用户“刷手机”​,百度Feed流背后的新技术装备有多牛?

导读&#xff1a;截止到2018年底&#xff0c;我国网民使用手机上网的比例已高达98.6%&#xff0c;移动互联网基本全方位覆盖。智能手机的操作模式让我们更倾向于通过简单的“划屏”动作&#xff0c;相对于传统的文本交互方式来获取信息&#xff0c;用户更希望一拿起手机就能刷到…

玩转高性能超猛防火墙nf-HiPAC

中华国学&#xff0c;用英文讲的&#xff0c;稀里糊涂听了个大概&#xff0c;不得不佩服西方人的缜密的逻辑思维&#xff0c;竟然把玄之又玄的道家思想说的跟牛顿定律一般&#xff0c;佩服。归家&#xff0c;又收到了邮件&#xff0c;还是关于nf-hipac的&#xff0c;不知不觉就…

ios 沙盒 plist 数据的读取和存储

plist 只能存储基本的数据类型 和 array 字典 [objc] view plaincopy - (void)saveArray { // 1.获得沙盒根路径 NSString *home NSHomeDirectory(); // 2.document路径 NSString *docPath [home stringByAppendingPathComponent:"Document…

FFmpeg实现获取USB摄像头视频流测试代码

通过USB摄像头(注&#xff1a;windows7/10下使用内置摄像头&#xff0c;linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice。头文件仅include avdevice.h即可&#xff0c;因为avdevice.h中会include avformat.h。libavdevice库是libavformat的一…

重磅!明略发布数据中台战略和三大解决方案

11月15日&#xff0c;明略科技在上海举办以“FASTER 聚变增长新动力”为主题的2019数据智能峰会&#xff0c;宣布“打造智能时代的企业中台”新战略&#xff0c;同时推出了两大新产品“新一代数据中台”和“营销智能平台”&#xff0c;以及三大行业解决方案&#xff0c;分别是“…

Android程序完全退出的三种方法

1. Dalvik VM的本地方法 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID&#xff0c;目前获取自己的也只有该API&#xff0c;否则从/proc中自己的枚举其他进程吧&#xff0c;不过要说明的是&#xff0c;结束其他进程不一定有权限&#xff0c;不然就…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(旧接口)

这里通过USB摄像头(注&#xff1a;windows7/10下使用内置摄像头&#xff0c;linux下接普通的usb摄像头(Logitech))获取视频流&#xff0c;然后解码&#xff0c;最后再用opencv显示。用到的模块包括avformat、avcodec和avdevice。libavdevice库是libavformat的一个补充库(comple…

IOS数据存储之文件沙盒存储

前言&#xff1a; 之前学习了数据存储的NSUserDefaults&#xff0c;归档和解档&#xff0c;对于项目开发中如果要存储一些文件&#xff0c;比如图片&#xff0c;音频&#xff0c;视频等文件的时候就需要用到文件存储了。文件沙盒存储主要存储非机密数据&#xff0c;大的数据。 …

剖析Focal Loss损失函数: 消除类别不平衡+挖掘难分样本 | CSDN博文精选

作者 | 图像所浩南哥来源 | CSDN博客论文名称&#xff1a;《 Focal Loss for Dense Object Detection 》论文下载&#xff1a;https://arxiv.org/pdf/1708.02002.pdf论文代码&#xff1a;https://github.com/facebookresearch/Detectron/tree/master/configs/12_2017_baselines…

windows下mysql开启慢查询

mysql在windows系统中的配置文件一般是my.ini,我的路径是c:\mysql\my.ini,你根据自己安装mysql路径去查找[mysqld]#The TCP/IP Port the MySQL Server will listen onport3306#开启慢查询log-slow-queries E:\Program Files\MySQL\MySQL Server 5.5\mysql_slow_query.loglong_…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(新接口)

在https://blog.csdn.net/fengbingchun/article/details/93975325 中给出了通过旧接口即FFmpeg中已废弃的接口实现通过摄像头获取视频流然后解码并显示的测试代码&#xff0c;这里通过使用FFmpeg中的新接口再次实现通过的功能&#xff0c;主要涉及到的接口函数包括&#xff1a;…

iOS经典讲解之获取沙盒文件路径写入和读取简单对象

#import "RootViewController.h" interface RootViewController () end 实现文件&#xff1a; implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [self path]; [self writeFile]; [self readingFi…

Google最新论文:Youtube视频推荐如何做多目标排序

作者 | 深度传送门来源 | 深度传送门&#xff08;ID:deep_deliver&#xff09;导读&#xff1a;本文是“深度推荐系统”专栏的第十五篇文章&#xff0c;这个系列将介绍在深度学习的强力驱动下&#xff0c;给推荐系统工业界所带来的最前沿的变化。本文主要介绍下Google在RecSys …

Jmeter 笔记

Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于Web应用测试但后来扩展到其他测试领域。 它可以用于测试静态和动态资源例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库&#xff0c; FTP 服务器&#…

王贻芳院士:为什么中国要探究中微子实验?

演讲嘉宾 | 王贻芳&#xff08;中国科学院院士、中科院高能物理研究所所长&#xff09;整理 | 德状出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;日前&#xff0c;在2019腾讯科学WE大会期间&#xff0c;中国科学院院士、高能物理研究所所长王贻芳分享了中微子与光电…

一个苹果证书供多台电脑开发使用——导出p12文件

摘要 在苹果开发者网站申请的证书&#xff0c;是授权mac设备的开发或者发布的证书&#xff0c;这意味着一个设备对应一个证书&#xff0c;但是99美元账号只允许生成3个发布证书&#xff0c;两个开发证书&#xff0c;这满足不了多mac设备的使用&#xff0c;使用p12文件可以解决这…

FFmpeg中AVDictionary介绍

FFmpeg中的AVDictionary是一个结构体&#xff0c;简单的key/value存储&#xff0c;经常使用AVDictionary设置或读取内部参数&#xff0c;声明如下&#xff0c;具体实现在libavutil模块中的dict.c/h&#xff0c;提供此结构体是为了与libav兼容&#xff0c;但它实现效率低下&…

RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个

问题现象RocketMQ3.2.2版本&#xff0c;测试时尝试发送消息时自动创建Topic&#xff0c;设置了队列数量为8&#xff1a;producer.setDefaultTopicQueueNums(8);同时设置broker服务器的配置文件broker.properties&#xff1a;defaultTopicQueueNums16但实际创建后从控制台及后台…

iOS各种宏定义

#ifndef MacroDefinition_h #define MacroDefinition_h //************************ 获取设备屏幕尺寸********************************************** //宽度 #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width //高度 #define SCREENH_HEIGHT [UIScree…

开源库libuuid简介及使用

libuuid是一个开源的用于生成UUID(Universally Unique Identifier&#xff0c;通用唯一标识符)的库&#xff0c;它的源码可从https://sourceforge.net/projects/libuuid/ 下载&#xff0c;最新版本为1.0.3&#xff0c;更新于2013年4月27日&#xff0c;此库仅支持在类Linux下编译…

深度学习会议论文不好找?这个ConfTube网站全都有

BDTC大会官网&#xff1a;https://t.csdnimg.cn/q4TY作者 | 刘畅 出品 | AI科技大本营&#xff08;ID:rgznai1000&#xff09;最近跟身边的硕士生、博士生聊天&#xff0c;发现有一个共同话题&#xff0c;大家都想要知道哪款产品能防止掉头发&#xff1f;养发育发已经成了茶余饭…

Java用for循环Map

为什么80%的码农都做不了架构师&#xff1f;>>> 根据JDK5的新特性,用For循环Map,例如循环Map的Key for(String dataKey : paraMap.keySet()) { System.out.println(dataKey ); } 注意的是,paraMap 是怎么样定义的,如果是简单的Map paraMap new …

iOS 应用发布到AppStore流程

iOS开发者&#xff0c;把开发出来的App上传到App Store是必须的。下面就来详细介绍下具体流程。 方法/步骤 1打开苹果开发者中心 打开后点击&#xff1a;Member Center 2如果你的电脑没有保存密码&#xff0c;则会提示你输入开发者帐号和密码&#xff0c;因为我的电脑已经保存了…

FFmpeg中编码类型为rawvideo无须解码直接显示测试代码

在 https://blog.csdn.net/fengbingchun/article/details/93975325 中介绍过通过FFmpeg可以直接获取usb视频流并解码显示的测试代码&#xff0c;当时通过usb获取到的视频流编码类型为AV_CODEC_ID_RAWVIDEO&#xff0c;像素格式为AV_PIX_FMT_YUYV422&#xff0c;其实编码类型为r…

一场高质量的技术盛会怎样炼成?「2019中国大数据技术大会」蓄势待发,还不快上车?...

2019年12月&#xff0c;一场轰动国内产业界、学术界、科研界及投资领域的顶级科技盛会即将拉开帷幕&#xff0c;它涵盖大数据、人工智能、云计算、AIoT、金融科技、智能制造等十几个前沿领域的热门话题。在过去十二年里&#xff0c;这场盛会从最初仅 60 余人参加的技术沙龙到如…