預先建立子程序的方式比為每個客戶端建立乙個程序的方式優越的地方在於當伺服器啟動時就將子程序建立好,當乙個客戶端連線至伺服器時選擇乙個可用的子程序處理,這樣可以節省到建立子程序的消耗。有乙個弊端是需要事先確定子程序的個數,當客戶端多於子程序的個數時,基於的客戶端只能等待可用的子程序。有一種解決方法就是動態的分配子程序的個數,當可用的子程序小於事先設定的閥值時,增加一定數量的子程序,相持當可用子程序多於事先設定的閥值時,減少一定數量的子程序。
這種方式的實現是利用了unix核心對檔案描述符的實現,讓所有的子程序全部監聽處於listen狀態的描述符(即呼叫accept函式),當乙個客戶端連線進來時所有的子程序被啟用,但是只有乙個程序可以與客戶端進行連線,其它的程序繼續進入阻塞狀態。為了防止這種競爭發生錯誤,可以加入鎖機制,只有得到鎖的程序才能與客戶端進行連線,可以用檔案鎖或執行緒鎖等機制實現。
例子:回射伺服器,即伺服器端接收客戶端來的資料,並將資料原樣返回給客戶端,**在centos5.0測試通過
伺服器端**:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define serv_port 2003
#define maxline 1024
#define listenq 4
int makelistenbyport(short port)
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(af_inet, sock_stream, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_addr.s_addr = htonl(inaddr_any);
servaddr.sin_port = htons(port);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, listenq);
return listenfd;
/* 客戶請求處理函式 */
void requestprocessfunc(int connfd)
char buf[maxline];
int n;
for(;;) else{
write(connfd, buf, n);
int main(int argc, char **argv)
int listenfd, connfd, maxfd, sockfd;
char buf[maxline];
struct sockaddr_in cliaddr;
int i;
int clilen, adrlen;
pid_t child;
/*根據端號建立監聽 */
listenfd= makelistenbyport(serv_port);
adrlen = sizeof(struct sockaddr);
/*建立5個子程序 */
for(i = 0; i < 5; i++) {
if((child = fork()) == 0) {
/* 每個子程序都迴圈的監聽 */
for(;;) {
clilen = adrlen;
if((connfd = accept(listenfd,(struct sockaddr *)&cliaddr, &clilen)) < 0){
if(errno == eintr)
continue;
else{
printf("accepterror!");
exit(0);
requestprocessfunc(connfd);
close(connfd);
/*父程序不做任何操作 */
for(;;) pause();
客戶端**:
#include
#include
#include
#include
#include
#include
#include
#define maxline 1024
#define serv_port 2003
void cli_str(file *fp, int sockfd)
char sendline[maxline];
char recvline[maxline];
memset(recvline, 0x00, sizeof(recvline));
memset(sendline, 0x00, sizeof(sendline));
printf("cli#");
while((fgets(sendline, maxline, fp)) != null) {
write(sockfd, sendline, strlen(sendline));
if(read(sockfd, recvline, maxline) == 0) {
printf("str_cli:serverterminated prematurely\n");
exit(0);
fputs(recvline, stdout);
fflush(stdout);
memset(recvline, 0x00, sizeof(recvline));
printf("cli#");
int main(int argc, char **argv)
int sockfd;
struct sockaddr_in servaddr;
if((sockfd = socket(af_inet, sock_stream, 0)) == -1) {
printf("socket error\n");
exit(0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
inet_pton(af_inet, argv[1],&servaddr.sin_addr);
servaddr.sin_port = htons(serv_port);
if((connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))== -1) {
printf("connect error\n");
exit(0);
cli_str(stdin, sockfd);
exit(0);
Unix網路程式設計伺服器設計方式之二
此方式首先伺服器端建立乙個監聽,並阻塞至accetp處,當乙個客戶端進行連線時,accept函式並啟用並返回,此時用fork函式建立乙個子程序,由子程序執行客戶請求處理程式,而父程序繼續監聽,等待其他的客戶端。此方式會建立很多的程序,程序個數受具體的作業系統的限制。這種併發伺服器的缺點在於建立乙個子...
Unix網路程式設計伺服器設計方式之六
此種方式是由主線程預先建立多個工作執行緒,並且主線程不斷的監聽連線請求,當有連線請求時先獲得鎖,並將連線放入到連線陣列中,並通知空閒的工作執行緒 即阻塞在條件等待處的工作執行緒 進行請求處理,工作執行緒得到通知後先在連線陣列中拿乙個可用的連線,並將其標記為已處理,然後釋放鎖,執行請求處理函式。此方式...
UNIX網路程式設計 併發伺服器(多程序)
以下程式的源 均是unix網路程式設計上的例子程式。intro daytimetcpsrv1.c include unp.h include include apueerror.h int main int argc,char argv tcp一般採用併發伺服器。當服務乙個客戶請求可能花費較長時間時...