Unix C語言編寫基於進程的小型併發服務器

併發介紹

若是邏輯控制流在時間上是重疊的,那麼它們就是併發的,能夠出如今計算機系統的不一樣層面上,硬件異常處理程序、進程和Unix信號處理程序都是併發的。併發能夠看做是操做系統內核用來運行多個應用程序的機制,可是併發不侷限於內核。它也能夠在應用程序中扮演角色。併發的主要做用有:訪問慢速IO設備;與人交互的程序;經過推遲工做以下降延遲;服務多個網絡客戶端的請求。併發一般能夠有三種,基於進程、基於IO多路複用、基於線程。 服務器

基於進程的併發

進程是一個程序運行的實例。每個進程都有本身獨立的地址空間,通常狀況下,包括文本區域、數據區域和堆棧。文本區域是存儲處理器執行的代碼;數據區域存儲變量和線程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。程序是一個沒有生命的實體,只有處理器賦予程序生命,而後由操做系統去執行它,它才能稱做一個實體,稱爲進程。 網絡

一個併發服務器的天然構造方法是,在父進程中接受客戶端的鏈接請求,而後建立一個子進程來爲每一個新客戶端提供服務。在鏈接接受請求以後,服務器派生一個子進程,這個子進程獲取服務器描述符表的完整拷貝,子進程關閉它的拷貝的監聽描述符,而父進程關閉它的已鏈接描述符,不然,將永遠不會釋放已鏈接描述符的文件表條目,並且由此引起的存儲器泄露將最終消耗盡可用的服務器,使系統崩潰。 併發

對於父、子進程間共享狀態信息,進程有一個很是清晰的模型:共享文件表,可是不共享用戶地址空間。進程有獨立的地址空間既是優勢,也是缺點,這樣一來,一個進程不可能不當心覆蓋另外一個進程的虛擬存儲器;另外一方面,獨立的地址空間使得進程之間共享信息變得更加困難。另外,基於進程的設計另外一個缺點是,每每運行比較慢,由於進程控制和IPC開銷比較高。 app

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
相關文章
相關標籤/搜索