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

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

  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

类似ngnix的多进程监听用例相关推荐

  1. Cocos Creator_实现策略_多点触控之触控管理器监听单例_TypeScript

    触控管理器(TypeScript实现) [主要功能] 1.实时访问每个触摸手指的状态(手指顺序,touch位置,按钮状态,Touch类) 2.使鼠标与触摸的API兼容访问 3.实时访问键盘按钮状态 4 ...

  2. php进程监听是什么意思,多进程监听同个端口及单进程监听多个端口的php版本实现...

    最近在看nginx设计原理时思考到两个问题,便是: 多个进程能否监听同个端口? 单个进程能否监听多个端口? 当然随着学习的深入,答案均是肯定的,在这个过程中笔者为了验证,用php写了两个例子,在这里分 ...

  3. oracle未获得监听器,无监听文件listener.ora的动态监听小例试验

    在数据库服务器上,监听文件的位置是:$ORACLE_HOME/network/admin/listener.ora 试验如下: 移动db服务器上的监听文件,如下命令: [oracle@ENMOEDU ...

  4. epoll监听文件_【原创】万字长文浅析:Epoll与Java Nio的那些事儿

    " Epoll 是Linux内核的高性能.可扩展的I/O事件通知机制. 在linux2.5.44首次引入epoll,它设计的目的旨在取代既有的select.poll系统函数,让需要大量操作文 ...

  5. 如何多个进程监听同一个端口

    1. 问题描述 一个进程监听端口,经验告诉我们,如果多次启动一个进程会报错:"Address already in use!".这是由于bind函数导致的,由于该端口号已经被第一个 ...

  6. 【京东个人中心】——Nodejs/Ajax/HTML5/Mysql爬坑之注册与登录监听

    一.引言 在数据库和静态页面都创建好之后,下面就该接着完成后台Node.js监听注册和登录的部分了.这个部分主要使用的技术是:Node.js的Express框架和ajax异步请求.登录和注册的代码实现 ...

  7. Linux中不同进程同一个端口,linux系统实现多个进程监听同一个端口

    通过 fork 创建子进程的方式可以实现父子进程监听相同的端口. 方法:在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程, ...

  8. python多进程关闭socket_用Python制作一个多进程UDP服务器,一个进程监听一个p

    我想用Python制作一个多进程UDP服务器,从一个类中为每个进程监听一个端口: processListener.py:import multiprocessing import socket cla ...

  9. java 观察者模式_重学 Java 设计模式:实战观察者模式「模拟类似小客车指标摇号过程,监听消息通知用户中签场景」...

    一.前言 知道的越多不知道的就越多 编程开发这条路上的知识是无穷无尽的,就像以前你敢说精通Java,到后来学到越来越多只想写了解Java,过了几年现在可能想说懂一点点Java.当视野和格局的扩大,会让 ...

最新文章

  1. 从零入门 Serverless | 一文搞懂函数计算及其工作原理
  2. 如何使PING命令带上日期,做长久的跟踪
  3. php浏览器头部获取,如何获取PHP以显示从浏览器收到的标头?
  4. minio分布式集群示例: 4节点,每节点4块盘
  5. html5实现的复古软件winamp的播放效果
  6. ue4打包问题的巧妙解决——二分回退大法!
  7. Easy RealMedia Producer使用向导
  8. 用python做计算器(超级版)
  9. 小米笔记本网卡驱动失效,无法联网
  10. 科学家用Google Earth发现千年古迹
  11. java jdk jre版本要一样吗a_JDK是什么?JRE是什么?JDK和JRE的区别?
  12. CCA(典型相关分析)
  13. Httpclient4 简介
  14. iOS开发初学者入门需要学习哪些知识?
  15. php下一页的代码,php 下一页的代码
  16. 微商做引流产品怎么做效果更好?为什么他人的生意这么好而自己没有生意呢?
  17. HMS华为账号登入全部流程加详解流程机制
  18. 如何查看Tomcat是否安装配置成功
  19. python怎么打开qq_Python怎么登录QQ空间?
  20. 【小甲鱼C语言】课后笔记第一章第二节——变量

热门文章

  1. 卡巴循环30天不限次数循环试用工具
  2. Swift学习: 从Objective-C到Swift
  3. Windows下搭建PHP开发环境
  4. cinder存储服务
  5. 正确生成浮点型的方法,解决sqlachemy Float浮点型的坑,生成float类型时,长度和精度均为0,导致查询不到结果!...
  6. Centos7 下 配置 rsync 以及 rsync+inotify 实时同步
  7. 你有没有试过“闭上眼”使用:京东、滴滴、QQ、支付宝?
  8. 如何设置 Linux 上 SSH 登录的 Email 提醒
  9. 微软批量授权版WINDOWS 10资料(截至到2015年11月,此处无下载地址)
  10. 提高性能的Varnish缓存方案