web伺服器端程式主要是兩個部分,一部分是主函式,一部門是命令處理函式。命令處理函式比較好理解就是針對客戶端不同的命令進行處理,與客戶端進行通訊。主函式也有兩個主要的功能,第一是要對程式進行初始化,其中包括建立監聽套接字並且繫結到位址和埠上,第二是建立子程序處理對應的連線請求。
1、主函式
web伺服器的主函式中第一是初始化程式,第二就是建立子程序。父程序一直監聽,子程序進行連線處理,提高伺服器端的處理能力,提高效率,流程圖如下:
主函式中的**如下所示:
#include "在主函式中也可以看出來父程序用來監聽,子程序用來處理連線請求。一開始進行linuxc學習的時候學到了程序的相關的知識,這是乙個多程序的程式例項,原理很簡單,但是需要注意的是子程序與父程序資源共享,因此要在父程序進行監聽的時候要關閉連線套接字,在子程序中要關閉監聽套接字,防止父子程序中相互干擾。主函式中程序初始化呼叫的init函式,函式**如下:common.h
"int main(void
)
if( (pid = fork()) < 0)
else
if(pid == 0)
}close(cfd);
/*跳出迴圈後關閉連線套接字描述符,通訊結束
*/exit(
0); /*
子程序退出 */}
else
close(cfd);
/*父程序關閉連線套接字,繼續監聽 */}
return
0; /*
伺服器程式很少有退出的時候
*/}
int init(struct sockaddr_in *sin, int *lfd, int2、命令處理模組sock_opt)
setsockopt(tfd, sol_socket, so_reuseaddr, &sock_opt, sizeof(int)); /*
設定套接字選項
*//*
繫結客戶端位址,具體位址沒有限制
*/if( (bind(tfd, (struct sockaddr *)sin, sizeof(struct sockaddr_in))) == -1
)
if( (listen(tfd, 20)) == -1
) *lfd =tfd;
return0;
}
根據之前的客戶端程式可以知道伺服器端有4個函式,分別是處理get、put、cd、ls這四個命令。
do_put函式處理get命令,函式成功返回0,失敗返回-1。客戶端發過來的get命令的格式為:get arg1。
引數說明:
cfd : 連線套接字的描述符
file : 客戶端請求的檔案的路徑
int do_put(int cfd, char *file)do_get函式處理put命令,成功返回0,失敗返回-1。客戶端發過來的 put命令的格式為:put arg1 arg2if( (fstat(fd, &statbuf)) == -1)
if(!s_isreg(statbuf.st_mode))
sprintf(buf,
"ok %d
", statbuf.st_size); /*
一切正常,傳送應答資訊,格式為:ok 傳送檔案的長度
*/if(my_write(cfd, buf, strlen(buf)) == -1) /*
傳送應答資訊
*/goto
end;
if ( (my_read(cfd, buf, max_line)) <= 0) /*
等待客戶端的應答資訊,應答碼是rdy
*/goto
end;
while(1)
else
}res = 0; /*
執行至此一切正常
*/end:
close(fd);
/*關閉檔案,注意不是關閉套接字
*/return
res;
}
該命令將客戶端的檔案傳送至伺服器,arg1為檔案的大小,arg2為傳送檔案在伺服器端的檔案路徑。
引數說明:
cfd : 連線套接字的描述符
file : 傳送過來的檔案在伺服器端的儲存路徑
int do_get(int cfd, char *file)do_cd函式處理cd命令,成功返回0,失敗返回-1,客戶端傳送過來的cd命令的格式為:put arg1else
}if( (fstat(fd, &statbuf)) == -1)
len =statbuf.st_size;
if(!s_isreg(statbuf.st_mode))
if(my_write(cfd, "
ok", 2) == -1) /*
傳送正確的應答碼
*/goto
end;
while(1)
else
if(len == 0
) else
/*讀取的位元組數小於0,出錯
*/goto
end;
}res = 0; /*
正常返回
*/end:
close(fd);
return
res;
}
該命令進入指定的伺服器端目錄,arg1為指定目錄的路徑
引數說明:
path:指定目錄的路徑
int do_cd(char *path)do_ls函式處理ls命令,成功返回0,失敗返回-1。客戶端傳送過來的ls命令的格式為:ls arg1。my_write(cfd,
"ok\n");
return0;
}
該命令列出當前伺服器端目錄下的檔案,arg1為指定目錄的路徑
引數說明:
path:指定目錄的路徑
int do_ls(char *path)if( (fstat(fd, &statbuf)) == -1)
if(!s_isreg(statbuf.st_mode))
sprintf(buf,
"ok %d
", statbuf.st_size); /*
一切正常傳送應答資訊,格式為: ok 傳送檔案的長度
*/if(my_write(cfd, buf, strlen(buf)) == -1) /*
傳送應答資訊
*/goto
end;
if ( (my_read(cfd, buf, max_line)) <= 0) /*
等待客戶端的應答資訊,應答碼是rdy
*/goto
end;
while(1)
else
}res = 0; /*
執行至此一切正常
*/end:
close(fd);
/*關閉檔案,注意不是關閉套接字
*/return
res;
}
24 實現http伺服器端
1.http hypertext transfer protocol超文字傳輸協議。超文字是可以根據客戶端請求而跳轉的結構化資訊。http協議是以超文字傳輸為目的而設計的應用層協議,是基於tcp ip實現的協議,實現該協議就相當於實現了web伺服器端。2.http協議又稱為無狀態的stateless...
WebSocket的C 伺服器端實現
由於需要在專案中增加websocket協議,與客戶端進行通訊,不想使用開源的庫,比如websocketpp,就自己根據websocket協議實現一套函式,完全使用c 實現。一 原理 websocket協議解析,已經在前面部落格裡面詳細講解過,可以參考部落格這裡就不詳細細說。伺服器端實現就是使用tcp...
多執行緒伺服器端的實現
1.單cpu系統中如何同時執行多個程序?請解釋該過程中發生的上下文切換。答 只有1個cpu cpu的運算裝置core 的系統中不是也可以同時執行多個程序嗎?只是因為系統將cpu時間分成了多個微小的塊後分配給了多個程序。為了分時使用cpu,需要 上下文切換 的過程。2.為何執行緒上下文切換更快?執行緒...