1.概念
與前面介紹的迴圈伺服器不同,併發伺服器對服務請求併發處理。而迴圈伺服器只能夠乙個乙個的處理客戶端的請求,顯然效率很低. 併發伺服器通過建立多個子程序來實現對請求的併發處理,但是由於不清楚請求客戶端的數目,因此很難確定子程序的數目。因此可以動態增加子程序與事先分配的子程序相結合的方法來實現併發伺服器。
2. 演算法流程
(1)tcp簡單併發伺服器:
伺服器子程序1:
socket(...);
bind(...);
listen(...);
while(1)
close(....);//關閉客戶端
伺服器子程序2:
socket(...);
bind(...);
listen(...);
while(1)
close(....);//關閉客戶端
伺服器子程序3
...............
...............
...............
(2)udp簡單併發伺服器
伺服器子程序1:
socket(...);
bind(...);
while(1)
close(...); //關閉客戶端連線
伺服器子程序2,3....與1相同.
這樣,同時到達多個請求,就分別由多個程序併發的處理,此演算法的的效能取決於請求的數目,如果請求數目越多,這樣的子程序就越多,那麼程序的切換開銷就會很大.而且還不容易確定子程序的數目,所以這是一種簡單的併發伺服器模型.
3.相關例項
(1)簡單併發伺服器tcp
伺服器:
#include
#include
#include
#include
#include
#include
#include
/**tcp併發伺服器,預先建立程序,同時到來的客戶端分別由不同的程序併發處理
**/#define port 8888
#define buffersize 1024
#define pidnum 2
static void handle(int s)
close(sc);}}
int main(int argc,char*argv)
//繫結位址到套接字
server_addr.sin_family=af_inet;
server_addr.sin_port=htons(port);
server_addr.sin_addr.s_addr=htonl(inaddr_any);
ret=bind(s,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(ret<0)
ret=listen(s,10);//監聽
//建立子程序處理同時到來的客戶端請求
for(i=0;i#include
#include
#include
#include
#include
#include
#include
#define port 8888
#define buffersize 1024
int main(int argc,char*argv)
bzero(&server_addr,sizeof(server_addr));
//將位址結構繫結到套接字
server_addr.sin_family=af_inet;
server_addr.sin_port=htons(port);
server_addr.sin_addr.s_addr=htonl(inaddr_any);
//連線伺服器
ret=connect(s,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(ret==-1)
memset(buffer,0,buffersize);
strcpy(buffer,"time");
size=send(s,buffer,strlen(buffer),0);
if(size<0)
memset(buffer,0,buffersize);
size=recv(s,buffer,buffersize,0);
if(size<0)
printf("%s",buffer);
close(s);
return 0;
}執行結果:
[root@localhost 14章伺服器模式]# ./circle-tcpc14
sat feb 18 10:28:59 2012
(2)udp簡單併發伺服器
伺服器:
#include
#include
#include
#include
#include
#include
#include
/**udp迴圈伺服器處理完乙個請求之後才能處理下乙個請求,而不能同時處理請求
udp併發伺服器通過事先建立程序,併發的處理來自客戶端的請求
缺點:事先建立好子程序,但不知道客戶端的數目,難以適應動態變化
**///建立2個程序,併發的處理客戶端的請求
#define port 8888
#define pidnum 2
#define buffersize 1024
//兩個子程序,分別併發的處理客戶端的請求
static void handle(int s)
} }}
int main(int argc,char*argv)
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=af_inet;
server_addr.sin_addr.s_addr=htonl(inaddr_any);
server_addr.sin_port=htons(port);
//將位址結構繫結到套接字描述符
ret=bind(s,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(ret==-1)
//接收資料並處理,主函式建立兩個程序,讓程序併發的處理請求
for(i=0;i客戶端:
#include
#include
#include
#include
#include
#include
#include
/**udp端,客戶端向伺服器傳送時間請求,伺服器返回相應的時間
**/#define port 8888
#define buffersize 1024
int main(int argc,char*argv)
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=af_inet;
server_addr.sin_addr.s_addr=htonl(inaddr_any);
server_addr.sin_port=htons(port);
memset(buffer,0,buffersize);
strcpy(buffer,"time");
//向伺服器傳送資料
size=sendto(s,buffer,strlen(buffer),0,(struct sockaddr*)&server_addr,sizeof(server_addr));
if(size<0)
//從伺服器接收資料
len=sizeof(server_addr);
size=recvfrom(s,buffer,buffersize,0,(struct sockaddr*)&server_addr,&len);
if(size<0)
//write(1,buffer,size);
printf("%s\n",buffer);
close(s);
return 0;
}總結:本文主要介紹了簡單的tcp與udp併發伺服器,並給出了例項.這種簡單的併發伺服器很難適應動態變化的客戶端請求,所以,接下來將介紹高階併發伺服器.
網路程式設計之併發網路程式設計
之前使用socket模組實現的網路程式設計都不能併發進行連線和通訊的,即乙個客戶端需要等待伺服器和另乙個客戶端通訊完成後才能和服務端進行連線和通訊。python3中提供有乙個高階內建模組socketserver來幫助我們進行併發的網路程式設計。socketserver模組處理網路請求的功能,可以通過...
併發程式設計之併發佇列
jdk 中提供了一系列場景的併發安全佇列。總的來說,按照實現方式的不同可分為阻塞佇列和非阻塞佇列,前者使用鎖實現,而後者則使用cas 非阻塞演算法實現。1 非阻塞佇列 concurrentlinkedqueue concurrentlinkedqueue是無界非阻塞佇列,內部使用單項鍊表實現 其中有...
Linux網路程式設計之廣播
1.概念 前面介紹的tcp,udp都是單播方式,即一對一.而廣播是一台主機向區域網內的所有主機傳送資料。這時,同一網段的所有主機都能接收到資料。傳送廣播包的步驟大致如下 1 確定乙個傳送廣播的介面,如eth0 2 確定廣播的位址,通過ioctl函式,請求碼設定為siocgifbrdaddr得到廣播的...