码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-08-17 12:21:33      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:

并发介绍

如果逻辑控制流在时间上是重叠的,那么它们就是并发的,可以出现在计算机系统的不同层面上,硬件异常处理程序、进程和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来测试程序:

zzw@zzw-ThinkPad-Edge-E430c:~$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is ‘^]‘.
hello
hello



root@zzw-ThinkPad-Edge-E430c:/home/zzw/doc_main/CProgram/Concurrency# ./echoserverp.o 8080
server received 7 bytes




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

标签:

原文地址:http://my.oschina.net/zzw922cn/blog/493397

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!