今天我们一起来聊聊多进程实现与多个客户端进行通信。

如果是在while中循环accept, 然后循环处理事情, 此时, 这种服务是迭代服务, 只能逐一处理客户端的请求, 后一个请求必须等前一个请求处理完毕, 无法并发处理, 真是急死人。 要实现并发, 我们可以考虑多线程, 也可以考虑多进程, 本文来说说后者。 在我们的多进程服务器模型中, 我们用父进程来处理连接(监听socket), 用fork子进程的方法来处理通信(通信socket), 各司其职, 美哉。

一旦涉及到fork, 就必须注意僵尸进程的处理, 所以, 我们要用waitpid进行收尸, 这一点, 我们已经说过了。 另外, 要注意, 父子进程共享socket句柄的文件表(如果不理解的话, 建议看看APUE), 所以close socket的时候, 只是使引用计数减1, 并不是真正地直接关闭socket(减为0才是真正的关闭)。

废话少说, 直接上菜。

服务端程序为:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

void sigChildFun(int sigNO)

{

pid_t pid;

int stat;

while((pid = waitpid(-1, &stat, WNOHANG)) > 0) // 循环收尸(僵尸进程), 此时waitpid不会阻塞

{

NULL;

}

return;

}

int main()

{

sockaddr_in servAddr;

memset(&servAddr,0,sizeof(servAddr));

servAddr.sin_family = AF_INET;

servAddr.sin_addr.s_addr = INADDR_ANY;

servAddr.sin_port = htons(8765);

int iListenSocket = socket(AF_INET, SOCK_STREAM, 0);

bind(iListenSocket, (sockaddr *)&servAddr, sizeof(servAddr));

listen(iListenSocket,5);

signal(SIGCHLD, sigChildFun);

while(1)

{

sockaddr_in clientAddr;

socklen_t iSize = sizeof(clientAddr);

memset(&clientAddr, 0, sizeof(clientAddr));

int iConnSocket = accept(iListenSocket,(sockaddr*)&clientAddr, &iSize);

if(iConnSocket < 0)

{

if(errno == EINTR || errno == ECONNABORTED)

{

continue;

}

else

{

printf("accept error, server");

return -1;

}

}

int tmpPid = fork();

if(tmpPid == 0)

{

close(iListenSocket); // 子进程让监听socket的计数减1, 并非直接关闭监听socket

char szBuf[1024] = {0};

snprintf(szBuf, sizeof(szBuf), "server pid[%u], client ip[%s]", getpid(), inet_ntoa(clientAddr.sin_addr));

write(iConnSocket, szBuf, strlen(szBuf) + 1);

while(1)

{

if(read(iConnSocket, szBuf, 1) <= 0)

{

close(iConnSocket); // 子进程让通信的socket计数减1

return -2; // 子进程退出

}

}

close(iConnSocket); // 子进程让通信的socket计数减1

return 0; // 子进程退出

}

close(iConnSocket); // 父进程让通信的socket计数减1

}

getchar();

close(iListenSocket); // 父进程让监听socket计数减1, 此时会关掉监听socket(因为之前子进程已经有此操作)

return 0;

}

启动它。

客户端程序为:

我们开启一个客户端, 此时如下:

客户端信息为:

服务端信息为:

可以看到, 服务端16402子进程是与客户端通信的进程, 父进程16096是监听的父进程(主进程)。

另外再开启一个客户端(不要关闭旧的客户端), 此时如下:

新客户端信息为:

服务端信息为:

可以看到, 父进程16096新开了一个子进程16497来与新的客户端进行通信。

我们关闭第一个客户端, 然后看到服务端为:

我们再关闭第二个客户端, 然后看到服务端为:

显然, 客户端退出后, 发FIN包, 服务端子进程的recv函数就为0, 退出子进程的while循环了, 因此, 对应的子进程就over了, 而且不会留下僵尸进程(有waitpid)。 而且, 我们可以看到, 负责连接管理(accept)的父进程(主进程)依然安然无恙, 优哉游哉地等待下一个客户端连接。

在这里, 我们可以看到, 这个服务器是并发的, 而不是迭代的。 什么意思呢? 你看, 即使子进程处理业务需要很久很久, 那么上述服务依然能并发地响应n个几乎同时到达的客户端, 此时,父进程开启n个子进程, 并发地工作, 并发地与客户端进行通信, 而且还互不干扰, 大大提升了服务满意度。

注:需要C/C++ Linux服务器开发学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

开源 多进程 框架 c++_linux fork多进程并发服务器模型之C/C++代码实战相关推荐

  1. 《一》php多进程编程:第一次fork

    <一>php多进程编程:第一次fork请添加链接描述 <二>守护进程介绍请添加链接描述 <三>用PHP编写守护进程请添加链接描述 工作原因,要用到php多进程,于是 ...

  2. python web框架 多线程和多进程_python的多线程和多进程(一)

    在进入主题之前,我们先学习一下并发和并行的概念: --并发:在操作系统中,并发是指一个时间段中有几个程序都处于启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但任一时刻点上只有一个程序在处理 ...

  3. 基于beego的高并发开源论坛框架Casnode

    Casnode是什么? Casnode是一款开源轻论坛程序.前端采用 javascript 和 React,后端主要为 beego 和 xorm.所以 xorm 支持的数据库,我们都支持哦.Casno ...

  4. ACache【轻量级的开源缓存框架】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 官方介绍 ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架.轻量到只有一个java文件(由十几个类精简 ...

  5. 开源 RPC 框架有哪些呢?

    开源 RPC 框架有哪些呢? 一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的. 跟语言平台绑定的开源 RPC 框架主要有下面几种. Dubbo:国内最早开源的 RPC 框架,由阿里巴 ...

  6. .NET 5 开源工作流框架elsa技术研究

    编者注: 工作流框架 elsa 是.NET基金会下面的开源项目,2.0版本即将在3月份发布,目前正在紧锣密鼓的开发之中,2020年2月份我也介绍过推荐一个很棒的开源工作流elsa-core ,今天给大 ...

  7. Java开源爬虫框架crawler4j

    花了两个小时把Java开源爬虫框架crawler4j文档翻译了一下,因为这几天一直在学习Java爬虫方面的知识,今天上课时突然感觉全英文可能会阻碍很多人学习的动力,刚好自己又正在接触这个爬虫框架,所以 ...

  8. 开源 RPC 框架有哪些

    一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的. 跟语言平台绑定的开源 RPC 框架主要有下面几种. Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末 ...

  9. html rpc文档,HTML5 DRM 正式成为 Web 标准,百度正式开源RPC框架brpc

    不顾近30%的成员反对,W3C(万维网联盟)正式宣布将加密媒体扩展(EME)--即集成DRM数字版权保护的API纳入HTML5建议标准. 自由软件基金会反对DRM的原因在于,如果在HTML5标准中加入 ...

最新文章

  1. 云计算如何帮助直播行业发展
  2. sqlserver2012——XML查询
  3. SAP License:谈对财务人的解惑
  4. [胡言乱语] 20170622
  5. 事务背书 ACID, CAP, BASE
  6. 手机页面操作栏的创建及WebFont的使用
  7. bufferedreader读取中文乱码_Python OpenCV与中文相关的三个常见问题
  8. Windows 内核会换为 Linux 吗?
  9. Hawkeye逃避机制和反调试技术分析
  10. 条形码编码规则及标准
  11. JDK11下载安装、JRE生成、环境配置
  12. 蜀山前传之二---------------第八回
  13. SAP AFS ARUN分货操作只争对销售订单行项目上的库存地进行
  14. 计算机组成原理实验箱教程,计算机组成原理实验箱的技术参数和性能指标
  15. 央企招聘:中国航空工业集团直属公司2023秋季招聘
  16. c语言版贪吃蛇《课程设计》
  17. The Shawshank Redemption-7
  18. 为了更好的实践与应用-机器人与ROS教学与培训
  19. PCB(AD)转HFSS进行电磁仿真
  20. 建设企业中台?你可能缺一个低代码平台!

热门文章

  1. 在C 语言中,请一定记得初始化局部变量!
  2. 我的10年富士康故事
  3. Android普通对话框标题居中,android开发Toolbar标题居中显示的解决方法
  4. 计算机图形学真实感显示代码,计算机图形学实验 - 真实感图形场景的生成
  5. 印度孟买机器人餐厅_印度孟买自动化展:该国最重要、规模最大的国际自动化展...
  6. 基于matlab的语音信号基本处理系统,基于matlab的语音信号处理及分析
  7. 进制转换应用场景_远程教育计算机应用基础统考知识点集中训练(二)_统考信息_网络远程教育...
  8. 基于python的系统构建_搭建一个基于python的深度学习环境
  9. linux驱动helloworld
  10. 【Linux】- 守护进程的启动方法