二、多程序方式
i/o復用雖然可以同時監聽多個檔案描述符,解決多個客戶端請求處理資料,但它本身是阻塞的,並且當多個檔案描述符同時就緒時,如果不採取額外措施,程式就只能按順序處理其中的每乙個檔案描述符,這使得伺服器看起來好像是序列工作的。如取快遞,所有物品在這放著監視著,當有人來取給他取,取的人多了就要排隊
如果要提高併發處理的能力,需要配合使用多執行緒和多程序等方法。我們實現併發伺服器,就是利用多程序/多執行緒來實現,就相當於取快遞的人排的隊太長了,我多僱幾個人,來乙個人乙個人取,兩個人派兩人給他取。
注意:本博文實現多執行緒、程序的工作方式,主要為了說明多執行緒、程序的使用方式,並沒有使用i/o復用,即沒有實現:i/o復用+多線/程序。
下圖是多執行緒處理邏輯圖:
它的主要邏輯就是:乙個主程序負責監聽檔案描述符,如果有客戶端描述符到達後,就建立乙個執行緒去處理它,再來乙個客戶端就再去建立執行緒處理。
主要**分為兩部分:
void* work_thread(void* arg)//執行緒函式
close(c)//關閉客戶端檔案描述符
}int main()//主函式
}
需要注意:我們對**進行編譯,因為包含執行緒,所以編譯時要連線庫:gcc -o thread thread.c -lpthread
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
intinitsocket()
//處理資料的執行緒
void
*work_thread
(void
* arg)
;int n=
recv
(c,buff,
127,0)
;if(n<=0)
printf
("%d:%s\n"
,c,buff)
;send
(c,"ok",2
,0);
}close
(c);
//一定要記得關閉,不然資源會浪費
}int
main()
pthread_t id;
int res=
pthread_create
(&id,
null
,work_thread,
(void
*)c)
;//執行緒介面,最後乙個元素為void*型別,所以要強轉c
}close
(sockfd)
;}
執行結果:
如果我們有100個客戶端,那麼就要建立100多個函式執行緒,但是每個伺服器的執行緒都有上限,並消耗大量的資源。我們每次的執行緒函式處理的資料也不是很多,所以資源浪費過多,系統反應時間會越來越慢。
仔細觀察兩個的執行結果,我們發現這個和使用i/o復用的效果一樣,但一定是兩種不同的機制,所以不要搞混:
cp thread.c process.c。
主要區別:1.為啥處理資料函式要關閉close(c),父程序也要。
答:因為fork()在建立子程序中,將檔案描述符複製了一次,將檔案描述次數++了一次,所以,所以父程序乙個,子程序乙個描述符,總共兩個,要關兩次。
2.關閉子程序時父程序還沒有處理子程序的狀態,所以會形成很多僵死程序。那麼解決辦法就是呼叫系統的wait()方法,那麼引入訊號量signal(si**hld,sig_funaction);當子程序資訊改變時就會產生si**hld訊號,然後就呼叫這個函式,這個函式裡呼叫wait(null)即可。
客戶端**和select一樣。
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
intinitsocket()
//處理資料的程序
void
work_proce
(int c)
;int n=
recv
(c,buff,
127,0)
;if(n<=0)
printf
("%d:%s\n"
,c,buff)
;send
(c,"ok",2
,0);
}close
(c);
//一定要記得關閉,不然資源會浪費
}void
sig_funaction
(int sign)
intmain()
pid_t pid=
fork()
;if(pid==0)
// 子程序
我們來解釋一下,為啥開啟了兩個客戶端但檔案描述符都是4。
程序描述符序號:乙個程序開啟乙個檔案sys_open(),確定乙個可用的檔案描述符,它會從0開始,然後乙個個找這個描述符是否被使用,使用了就繼續走,沒有被使用那就是它了。每個程序會預設開啟三個檔案描述符:0:標準輸入,1:標準輸出,2標準錯誤輸出,所以accept()檔案描述符最多從3開始。
我們**中,在父程序的處理是關閉檔案描述符,在子程序處理描述符時,它已經關閉當前描述符,等待新的連線了,新的連線又accept(),還是從4開始。畫個圖理解一下:
根據上圖我們可以清楚的看到因為父程序每次把檔案描述符給子程序後它都會斷開和此描述符的連線,所以再次建立會從4開始。這也給我們說明了,判斷有幾個客戶端不可以只通過檔案描述符來判斷。
加油哦!?。
伺服器併發處理架構
網路伺服器如何處理併發請求的模型稱之為多工體系結構。1.inetd模式 在大部分unix作業系統中,預設的多工體系結構是inetd應用程式。通用的網路伺服器體系結構inetd分為兩個部分 主服務程序和客戶服務程序。主服務程序通常用於等待客戶端的連線請求。一旦客戶端發起乙個請求,主伺服器將建立連線,同...
HTTP系列(五) 伺服器的工作
在前面的所有文章中,都是以客戶端的角度來出發的,到目前為止,我們只談到伺服器的職能就是處理請求,返回響應。但事實上,這裡面還有一些小細節需要注意,所以,本文就來談談伺服器的工作。前面說的沒錯,伺服器就是用於處理請求,返回響應的。那麼,在這個過程裡面,可以具體的分為以下的七個步驟 1.建立連線 接受乙...
伺服器設計 處理併發請求
伺服器設計技術有很多,按使用的協議來分有tcp伺服器和udp伺服器。按處理方式來分有迴圈伺服器和併發伺服器。在網路程式裡面,一般來說都是許多客戶對應乙個伺服器,為了處理客戶的請求,對服務端的程式就提出了特殊的要求。目前最常用的伺服器模型有 迴圈伺服器 伺服器在同一時刻只能響應乙個客戶端的請求 併發伺...