多进程并发服务器


       服务器server执行accept函数等待客户端A,B,C,D与之建立连接,假设客户端A与服务器建立连接时,服务器在就创建一个子进程,子进程负责与客户端A进行数据交互, (如果其他客户端再与服务器进行连接,而服务器忙着与A进行数据交互,则不会顾及其他客户端,这也是他的缺点),而父进程则继续监听其他客户端,当其他客户端进行连接时,服务器再创建一个新的子进程与之进行交互.

当父进程与与客户端连接完成后,会产生一个cfd和lfd , 当fork()产生一个子进程时,则会将这个cfd与lfd 继承,cfd可以用于与客户端进行数据交互,而lfd对于子进程来说并没有用处,所以子进程要将继承的lfd关闭.对于父进程来说父进程不需要与其他客户端进行数据交互,所以父进程需要关闭cfd.

子进程完成与客户端的数据交互后,子进程会退出变成僵尸进程,所以父进程要对子进程进行回收.可以用回调机制,利用信号进行处理:利用SIGCHLD注册信号捕捉函数,在捕捉函数内调用waitpid()回收子进程

使用多进程并发服务器时要考虑以下几点:

  1. 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)
  2. 系统内创建进程个数(与内存大小相关)
  3. 进程创建过多是否降低整体服务性能(进程调度)

多线程高并发服务器实现将字符串转化大写

客户端往服务器端发送字符串,服务器把字符串转换成大写之后再发送回给客户端。

大致流程:

server.cpp

#include <iostream>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <strings.h>
#include <assert.h>
using namespace std;#define MAXLINE 4096
#define SERV_PORT 8000
//信号捕捉函数,信号:SIGCHLD:当子进程状态发生变化(退出或暂停)时产生
void do_sigchild(int num){while(waitpid(0,NULL,WNOHANG) > 0){//回收子进程}
}int main(){struct sockaddr_in servaddr,cliaddr;socklen_t cliaddr_len = sizeof(cliaddr);int listenfd,connfd;char buf[MAXLINE];char str[INET_ADDRSTRLEN];struct sigaction newact;newact.sa_handler = do_sigchild;sigemptyset(&newact.sa_mask);newact.sa_flags = 0;sigaction(SIGCHLD,&newact,NULL);listenfd = socket(AF_INET,SOCK_STREAM,0);assert(listenfd >= 0);//重用本地地址,socket之后bind之前int opt = 1;setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));bzero(&servaddr,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);int ret = bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));assert(ret != -1);ret = listen(listenfd,20);assert(ret != -1);cout << "Accepting connections ..." << endl;while(1){connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddr_len);pid_t pid = fork();if(pid == 0){close(listenfd);//子进程将继承得来的listenfd关闭while(1){int n = read(connfd,buf,MAXLINE);//读取客户端数据if(n == 0){cout << "the other side has been closed. " << endl;break;}//输出客户端IP地址和PORTcout << "Received from " << inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str))<< " at POTR "<< ntohs(cliaddr.sin_port)<< endl;//将小写转换为大写for(int i = 0;i < n;i++){buf[i] = toupper(buf[i]);}write(STDOUT_FILENO,buf,n);//输出到服务器的屏幕write(connfd,buf,n);//输出到客户端}close(connfd);return 0;}else if(pid > 0){close(connfd);//父进程不需要与客户端进行数据交互,所以关闭connfd}else{perror("fork error");}}return 0;
}

client.cpp

#include <iostream>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <string.h>
using namespace std;
#define SERV_PORT 8000
#define MAXLINE 4096
int main(){struct sockaddr_in servaddr;char buf[MAXLINE];int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd >= 0);bzero(&servaddr,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);int ret = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(sockaddr));if(ret < 0){perror("connect error ");exit(1);}while(fgets(buf,MAXLINE,stdin) != NULL){//读取键盘数据write(sockfd,buf,strlen(buf));//将数据写到服务器int n = read(sockfd,buf,MAXLINE);//从服务器读取数据if(n == 0){cout << "the other side has been closed" << endl;break;}else{write(STDOUT_FILENO,buf,n);//将从服务器读到的数据显示到客户端屏幕上}}close(sockfd);return 0;
}

多进程并发服务器C++实现字符串小写到大写转换相关推荐

  1. 网络编程-C语言实现多进程并发服务器

    在Linux操作系统下,服务器通过fork()复制已调用的进程来创建子进程,以此来实现多进程并发服务器 功能:客户端发送任意字符串,服务器端将字符串小写转大写toupper();并返回给客户端,客户端 ...

  2. 计算机网络套接字编程实验-TCP多进程并发服务器程序与单进程客户端程序(简单回声)

    1.实验系列 ·Linux NAP-Linux网络应用编程系列 2.实验目的 ·理解多进程(Multiprocess)相关基本概念,理解父子进程之间的关系与差异,熟练掌握基于fork()的多进程编程模 ...

  3. linux网路编程之多进程并发服务器

    1)使用多进程并发服务器考虑的因素: (1)父进程描述最大文件描述符的个数(父进程需要关闭accept返回的新文件描述符) (2)系统内可创建进程的个数(与内存大小相关) (3)进程创建过多是否降低整 ...

  4. C++网络编程(四):多进程并发服务器

    部分内容转自Linux并发服务器编程之多进程并发服务器. 目录 前言 创建进程 Linux下的进程 进程创建函数fork与vfork exec函数 使用fork函数实现多进程并发服务器 分割I/O程序 ...

  5. Linux网络编程基础<多进程并发服务器>

    一.应用场景 最简单的socket示列代码只能一个客户端连接一个服务器,并不支持多个客户端对服务器的连接,为了能让多个客户端进行连接所以需要多进程或者多线程处理 二.思路解析 服务器端的程序是俩个套接 ...

  6. C/C++ _wcsupr_s 函数 – unicode 字符串小写转大写 - C语言零基础入门教程

    目录 一._wcsupr_s 函数简介 二._wcsupr_s 函数实战 三.注意问题 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 零 ...

  7. C/C++ _strupr_s 函数 – 字符串小写转大写 - C语言零基础入门教程

    目录 一._strupr_s 函数简介 二._strupr_s 函数实战 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 零基础 C/C+ ...

  8. 27.Linux网络编程 掌握三次握手建立连接过程掌握四次握手关闭连接的过程掌握滑动窗口的概念掌握错误处理函数封装实现多进程并发服务器实现多线程并发服务器

    基本概念叫协议 什么叫协议? 协议是一个大家共同遵守的一个规则, 那么在这个网络通信当中,其实就是双方通信和解释数据的一个规则,这个概念 你也不用记,你只要心里明白就可以了, 分层模型, 物数网传会表 ...

  9. 网络编程-----多进程并发服务器实现

    案例要求 实现一个多进程并发的服务器,可以实现多个客户端的连接. 把每个连接的客户端的ip和port输出,而且每个客户端的输入都在服务器输出 把客户端的小写转化为大写 声明:因个人能力有限,本文仅是个 ...

最新文章

  1. 昌吉学院计算机工程系毕业后安排工作嘛,0昌吉学院.doc
  2. Flex制作的一个Mp3播放器
  3. Java中只有按值传递,没有按引用传递!
  4. ubuntu 安装java jdk_「ubuntu安装jdk」Ubuntu安装jdk8的两种方式 - seo实验室
  5. 简约PHP导航源码个人页介绍
  6. Python之路(第十七篇)logging模块
  7. java 布局实例,HarmonyOS Java UI之StackLayout布局示例
  8. 简单的3个SQL视图搞定所有SqlServer数据库字典 (转载)
  9. final可以修饰哪些java名词_Java关键知识点 - Java final关键字到底修饰了什么?
  10. cnn风格迁移_图像风格迁移详解
  11. python爬虫百度地图_Python抓取百度地图的数据
  12. 2021年山东省安全员C证报名考试及山东省安全员C证操作证考试
  13. 上海电力大学计算机科学与技术学院,栗风永 - 上海电力大学 - 计算机科学与技术学院...
  14. Windows 模拟弱网环境(Network Emulator for Windows Toolkit)
  15. 计蒜客 蒜头君的积木
  16. Stream操作666
  17. 如何在C加加的面向对象写游戏 我的世界
  18. vbs恶意脚本_vbs恶意软件删除程序的分析
  19. 密码学数论基础部分总结之 有限域GF(p) Galois Fields
  20. 3-Win10屏幕截图成功后去哪里找?以及如何修改默认保存位置?

热门文章

  1. 基于高分辨影像城市绿地信息提取项目流程
  2. Delphi中绘制圆角矩形的窗体
  3. PHP Swoole的基本用法
  4. Blender入门必学之如何拖动地面(即拖动视图)及如何弹出工具栏右下角选项
  5. 浅谈PHP实现订阅消息添加到个人模板库
  6. 织梦dede免费小程序插件
  7. 对称加密算法:长期有效的加密
  8. 友谊的小船永远都不会翻【张悦生日快乐】
  9. RNN的一些高级用法-以温度预测问题为例
  10. 可持续能源技术:改变世界的新方案