從以前的程序中也能夠總結出來通常面向鏈接的服務器程序的代碼框架,通常的模型以下所示:算法
int main() { socket(…); bind(…); listen(…); while(1) { accept(…); while(1) { pead(…); process(…); write(…); } close(…); } return 0; }
這種面向鏈接的服務器有一個很大的弊端:服務器一次只能處理一個客戶端的請求,只有在這個客戶的全部請求都知足以後,服務器才能繼續處理後面的請求。若是有一個客戶端佔用服務器,後邊的客戶機都不能工做。這樣的模型效率過低,不適合實際使用。一種很好的解決辦法就是使用併發服務器的框架,流程圖以下:服務器
併發服務器的通常模型模型代碼以下:併發
int main(void) { socket(…); bind(…); listen(…); while(1) { accept(…); if(forhk(…) == 0) { while(1) { close(…); read(…); process(…); write(…); } close(…); exit(…); } else close(…); } close(…); return 0; }
上邊的模型中,子進程負責處理鏈接請求,所以關閉監聽套接字;父進程繼續監聽鏈接請求,所以關閉鏈接套接字。當服務器程序退出後,則關閉監聽套接字。因而可知,在併發服務器的代碼框架中,套接字的建立和關閉也是一一對應的,可使用這種方法來檢查本身的程序是否正確。框架
對於面向鏈接的服務器,併發服務器能夠解決循環服務器客戶機獨佔服務器的狀況,可是也存在一些新的問題:socket
一、服務器要建立子進程來處理客戶端的鏈接請求,可是建立子進程是一種很是消耗資源的操做。爲了提升效率必須使用更好的算法。spa
二、子進程結束運行後,注意對其資源的回收,不然會形成大量的殭屍進程,這可能會致使系統崩潰。code
在使用併發服務器程序的代碼框架的時候,須要注意上邊這兩個問題。blog