日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

服务器编程模型

發布時間:2024/4/18 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 服务器编程模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在網絡程序里面,通常的來講都是許多客戶機對應一個服務器.為了處理客戶機的請求, 對服務端的程序就提出了特殊的要求.咱們學習一下目前最經常使用的服務器模型.

循環服務器:循環服務器在同一個時刻只能夠響應一個客戶端的請求

并發服務器:并發服務器在同一個時刻能夠響應多個客戶端的請求


9.1 循環服務器:

UDP服務器
UDP循環服務器的實現很是簡單:
UDP服務器每次從套接字上讀取一個客戶端的請求,處理, 而后將結果返回給客戶機.

能夠用下面的算法來實現.

?? ?socket(...);
?? ?bind(...);
?? ?while(1)
?? ?{
?? ??? ?recvfrom(...);
?? ??? ?process(...);
?? ??? ?sendto(...);
?? ?}

由于UDP是非面向鏈接的,沒有一個客戶端能夠總是占住服務端. 只要處理過程不是死循環, 服務器對于每個客戶機的請求老是可以知足.

9.2 循環服務器:

TCP服務器
TCP循環服務器的實現也不難:TCP服務器接受一個客戶端的鏈接,而后處理,完成了這個客戶的全部請求后,斷開鏈接.

算法以下:

socket(...);
bind(...);
listen(...);

while(1)
{
?? ?accept(...);
?? ?while(1)
?? ?{
?? ??? ?read(...);
?? ??? ?process(...);
?? ??? ?write(...);
?? ?}
?? ?close(...);
}

TCP循環服務器一次只能處理一個客戶端的請求.只有在這個客戶的全部請求都知足后, 服務器才能夠繼續后面的請求.這樣若是有一個客戶端占住服務器不放時,其它的客戶機都不能工做了.所以,TCP服務器通常不多用循環服務器模型的.

9.3 并發服務器:???? TCP服務器
為了彌補循環TCP服務器的缺陷,人們又想出了并發服務器的模型. 并發服務器的思想是每個客戶機的請求并不禁服務器直接處理,而是服務器建立一個 子進程來處理.

算法以下:

?? ?socket(...);
?? ?bind(...);
?? ?listen(...);
?? ?while(1)
?? ?{
?? ??? ?accept(...);
?? ??? ?if(fork(..)==0)
?? ??? ?{
?? ??? ??? ??? ?while(1)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?read(...);
?? ??? ??? ??? ??? ?process(...);
?? ??? ??? ??? ??? ?write(...);
?? ??? ??? ??? ?}
?? ??? ??? ??? ?close(...);
?? ??? ??? ??? ?exit(...);
?? ??? ?}
?? ?close(...);
?? ?}

TCP并發服務器能夠解決TCP循環服務器客戶機獨占服務器的狀況. 不過也同時帶來了一個不小的問題.
為了響應客戶機的請求,服務器要建立子進程來處理. 而建立子進程是一種很是消耗資源的操做.

9.4 并發服務器:

多路復用I/O
為了解決建立子進程帶來的系統資源消耗,人們又想出了多路復用I/O模型.

首先介紹一個函數select

int select(int nfds,
?? ??? ?fd_set *readfds,fd_set *writefds,
?? ?? fd_set *except fds,
?? ?? struct timeval *timeout
?? ?? )

void FD_SET(int fd,fd_set *fdset)

void FD_CLR(int fd,fd_set *fdset)

void FD_ZERO(fd_set *fdset)

int FD_ISSET(int fd,fd_set *fdset)

通常的來講當咱們在向文件讀寫時,進程有可能在讀寫出阻塞,直到必定的條件知足.

?好比咱們從一個套接字讀數據時,可能緩沖區里面沒有數據可讀(通訊的對方尚未發送數據過來),
?這個時候咱們的讀調用就會等待(阻塞)直到有數據可讀.若是咱們不 但愿阻塞,
?咱們的一個選擇是用select系統調用.?
?
?只要咱們設置好select的各個參數,那么當文件能夠讀寫的時候select回"通知"咱們 說能夠讀寫了.?
?readfds全部要讀的文件? 文件描述符的集合
writefds全部要寫的文件?? 文件描述符的集合

exceptfds其余的服要向咱們通知的文件描述符

timeout超時設置.

nfds全部咱們監控的文件描述符中最大的那一個加1

在咱們調用select時進程會一直阻塞直到如下的一種狀況發生.?
1)有文件能夠讀.
2)有文件能夠寫.
3)超時所設置的時間到.

為了設置文件描述符咱們要使用幾個宏. FD_SET將fd加入到fdset

FD_CLR將fd從fdset里面清除

FD_ZERO從fdset中清除全部的文件描述符

FD_ISSET判斷fd是否在fdset集合中

使用select的一個例子

int use_select(int *readfd,int n)
{
??? ??? fd_set my_readfd;
??? ??? int maxfd;
??? ??? int i;
??? ????
??? ??? maxfd=readfd[0];
??? ????
??? ??? for(i=1;i<n;i++)
??? ??? {
??? ??? ??? if(readfd[i]>maxfd) maxfd=readfd[i];
??? ??? }
??? ????
??? ????
??? ????
??? ??? while(1)
??? ??? {
??? ??? ??? /* 將全部的文件描述符加入 */
??? ??? ??? FD_ZERO(&my_readfd);
??? ??? ????
??? ??? ??? for(i=0;i<n;i++)
??? ??? ??? FD_SET(readfd[i],*my_readfd);
??? ??? ????
??? ??? ??? /* 進程阻塞 */
??? ??? ??? select(maxfd+1,& my_readfd,NULL,NULL,NULL);
??? ??? ????
??? ??? ??? /* 有東西能夠讀了 */
??? ??? ??? for(i=0;i<n;i++)
??? ??? ??? {
??? ??? ??? ??? if(FD_ISSET(readfd[i],&my_readfd))
??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? /* 原來是我能夠讀了 */
??? ??? ??? ??? ??? ??? we_read(readfd[i]);
??? ??? ??? ??? }
??? ??? ??? }
??? ??? }
}

使用select后咱們的服務器程序就變成了.


初始話(socket,bind,listen);

while(1)
{
??? ??? 設置監聽讀寫文件描述符(FD_*);
??? ????
??? ??? 調用select;
??? ????
??? ??? 若是是傾聽套接字就緒,說明一個新的鏈接請求創建
??? ??? {
??? ??? ??? 創建鏈接(accept);
??? ??? ??? 加入到監聽文件描述符中去;
??? ??? }
??? ??? 不然說明是一個已經鏈接過的描述符
??? ??? {
??? ??? ??? 進行操做(read或者write);
??? ??? }

}

多路復用I/O能夠解決資源限制的問題.著模型其實是將UDP循環模型用在了TCP上面. 這也就帶來了一些問題.如因為服務器依次處理客戶的請求,因此可能會致使有的客戶 會等待好久.

?并發服務器:??????? UDP服務器
人們把并發的概念用于UDP就獲得了并發UDP服務器模型.?
?并發UDP服務器模型實際上是簡單的.和并發的TCP服務器模型同樣是
?建立一個子進程來處理的 算法和并發的TCP模型同樣.

除非服務器在處理客戶端的請求所用的時間比較長之外,人們實際上不多用這種模型.

總結

以上是生活随笔為你收集整理的服务器编程模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。