Unix C语言编写基于进程的小型并发服务器

并发介绍

如果逻辑控制流在时间上是重叠的,那么它们就是并发的,可以出现在计算机系统的不同层面上,硬件异常处理程序、进程和Unix信号处理程序都是并发的。并发可以看作是操作系统内核用来运行多个应用程序的机制,但是并发不局限于内核。它也可以在应用程序中扮演角色。并发的主要作用有:访问慢速IO设备;与人交互的程序;通过推迟工作以降低延迟;服务多个网络客户端的请求。并发通常可以有三种,基于进程、基于IO多路复用、基于线程。

基于进程的并发

进程是一个程序运行的实例。每一个进程都有自己独立的地址空间,一般情况下,包括文本区域、数据区域和堆栈。文本区域是存储处理器执行的代码;数据区域存储变量和线程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。程序是一个没有生命的实体,只有处理器赋予程序生命,然后由操作系统去执行它,它才能称作一个实体,称为进程。

一个并发服务器的自然构造方法是,在父进程中接受客户端的连接请求,然后创建一个子进程来为每个新客户端提供服务。在连接接受请求之后,服务器派生一个子进程,这个子进程获取服务器描述符表的完整拷贝,子进程关闭它的拷贝的监听描述符,而父进程关闭它的已连接描述符,否则,将永远不会释放已连接描述符的文件表条目,而且由此引发的存储器泄露将最终消耗尽可用的服务器,使系统崩溃。

对于父、子进程间共享状态信息,进程有一个非常清晰的模型:共享文件表,但是不共享用户地址空间。进程有独立的地址空间既是优点,也是缺点,这样一来,一个进程不可能不小心覆盖另一个进程的虚拟存储器;另一方面,独立的地址空间使得进程之间共享信息变得更加困难。另外,基于进程的设计另一个缺点是,往往运行比较慢,因为进程控制和IPC开销比较高。

Unix C实现基于进程的小型并发服务器

本程序在Unix 环境下用C语言开发的,并且调用了csapp.h的现成头文件。

//本程序是一个基于多进程的并发echo服务器,父进程派生一个子进程来处理每个新的连接请求
#include "csapp.h"
//echo程序,用于向客户端发送响应主体
void echo(int connfd)
{
	int n;
	char buf[MAXLINE];
	rio_t rio;

	rio_readinitb(&rio,connfd);
	//带缓冲的读取函数
	while((n=rio_readlineb(&rio,buf,MAXLINE))>0) {
		//向连接符写入内容
		printf("server received %d bytes \n",n);
		rio_writen(connfd,buf,n);
	}
}

//信号处理函数,用于处理僵死进程,即回收已经终止的进程给系统带来的资源占用
void sigchld_handler(int sig)
{
	//-1代表回收父进程的子进程组,由于unix信号是不排队的,因此必须准备好回收多个僵死子进程的准备
	while(waitpid(-1,0,WNOHANG)>0)
		;
	return;
}

int main(int argc,char **argv)
{
	int listenfd,connfd,port;
	socklen_t clientlen=sizeof(struct sockaddr_in);
	struct sockaddr_in clientaddr;

	if(argc!=2) {
		fprintf(stderr,"usage :%s <port>\n",argv[0]);
		exit(0);
	}
	//将字符串转化为整型,端口号
	port=atoi(argv[1]);
	//启动信号处理函数监听器
	signal(SIGCHLD,sigchld_handler);
	//启动服务器监听描述符
	listenfd=open_listenfd(port);
	while(1) {
		//已连接描述符,接受连接
		connfd=accept(listenfd,(SA *)&clientaddr,&clientlen);
		//开辟子进程,用于处理连接请求
		if(fork()==0) {
			//由于子进程共享父进程的所有资源,因此先关闭监听描述符,再调用请求体命令,然后关闭已连接描述符,并且正常终止此进程
			close(listenfd);
			echo(connfd);
			close(connfd);
			exit(0);
		}
		//关闭父进程的已连接描述符
		close(connfd);
	}
}

使用telnet来测试程序:

[email protected]:~$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is ‘^]‘.
hello
hello
[email protected]:/home/zzw/doc_main/CProgram/Concurrency# ./echoserverp.o 8080
server received 7 bytes
时间: 2024-11-08 20:48:47

Unix C语言编写基于进程的小型并发服务器的相关文章

Unix C语言编写基于IO多路复用的小型并发服务器

背景介绍 如果服务器要同时处理网络上的套接字连接请求和本地的标准输入命令请求,那么如果我们使用accept来接受连接请求,则无法处理标准输入请求;类似地,如果在read中等待一个输入请求,则无法处理网络连接的请求. 所谓I/O多路复用机制,就是说通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但 select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而还

基于进程池的多进程服务器通信

代码来源:游双的linux高性能服务器编程 主进程创建一个进程池,当有客户端发送请求时,主进程选择一个进程与该客户端进行通信,为了简单期间,去掉了一些信号处理代码,其中信号的用法可以参考基于多进程的网络聊天程序 服务器代码如下: #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h&

TCP/IP 网络编程 (抄书笔记 3) -- 僵尸进程和多任务并发服务器

TCP/IP 网络编程 (抄书笔记 3) – 僵尸进程和多任务并发服务器 TCP/IP 网络编程 (抄书笔记 3) – 僵尸进程和多任务并发服务器 Table of Contents 僵尸进程的产生 避免僵尸进程 信号 多任务的并发服务器 僵尸进程的产生 子进程先退出, 父进程没有退出 ==> 僵尸进程 父进程先退出, 子进程没有退出 ==> 子进程被 0 号进程回收, 不会产生僵尸进程 pid_t pid = fork(); if (pid == 0) { // child printf(&

linux僵死进程与并发服务器编程

序 僵死(zombie)进程简而言之就是:子进程退出时,父进程并未对其发出的SIGCHILD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程. 因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源.对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求.如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源.如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能. 查

基于Perfect用Swift语言编写Slack聊天机器人

基于Perfect用Swift语言编写Slack聊天机器人 本项目是专门为Slack聊天机器人定制的模板服务器. 完整的源代码下载在Github https://github.com/PerfectServers/SlackBot 在本项目模板中,一个聊天机器人可以加入授权频道,读取频道内所有用户发送的"曲奇"并记录在案,而且可以直接答复用户的有关曲奇饼干的问题. 预备知识 在您决定编译.测试或者部署您自己的基于Perfect软件框架体系的聊天机器人之前,以下基础知识??不可或缺??:

shell简介 linux由什么语言编写

1.shell简介 Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言.作为命令语言,它交互式地解释和执行用户输入的命令:作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支.它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序.建立文件并以并行的方式协调各个程序的运行.因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其

根据Unix哲学来编写你的HTML5 Websocket服务器来实现全双工通信

websocketd代表WebSocket的守护进程 websocketd处理的是浏览器和服务器之间的WebSocket连接,它会启动你所指定的服务器端应用来对WebSockets进行处理,然后在浏览器和服务器应用之间进行消息的传递. 在20年前的话,有一项叫做CGI的技术做的工作类似,但现在这项技术将会被websocket所取代. 语言无关 只要你的服务器应用是可以从命令行进行运行的,你就可以为你的服务器应用编写WebSocket终端服务. 无需额外的库的支持 通过WebSocketd进行信息

Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架

转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架.Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器. Leaf 的关注点: 良好的使用体验.Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率 稳定性.Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃 多核支持.Leaf 通过模块机制和 leaf

Web2py是一个用Python语言编写的免费的开源Web框架

Zope 2是一款基于Python的Web应用框架,是所有Python Web应用程序.工具的鼻祖,是Python家族一个强有力的分支.Zope 2的"对象发布"系统非常适合面向对象开发方法,并且可以减轻开发者的学习曲线,还可以帮助你发现应用程序里一些不好的功能. Web2py是一个用Python语言编写的免费的开源Web框架,旨在敏捷快速的开发Web应用,具有快速.可扩展.安全以及可移植的数据库驱动的应用,遵循LGPLv3开源协议. Web2py提供一站式的解决方案,整个开发过程都可