web/http服務器實現


項目開發流程

  1. 需求分析:實現基本的HTTP服務器,支持瀏覽器的訪問(支持標準http協議)
    • 接收瀏覽器發送HTTP請求;
    • 解析請求數據,請求方式(GET),請求文件(html…),協議版本;
    • 根據請求構建響應頭,發送響應頭:
      HTTP/1.1 200 Ok
      HTTP/1.1 404 File not found
    • 根據請求文件,從服務器目錄中獲取對應的文件,發送給瀏覽器。
  2. 概要設計:繪製基本框圖
    在這裏插入圖片描述
  3. 詳細設計:繪製程序流程圖
    web整體框架總流程
    總流程
    最外層流程
    在這裏插入圖片描述

程序讀取配置文件流程
在這裏插入圖片描述
子進程處理客戶端請求流程
在這裏插入圖片描述
服務器初始化流程
在這裏插入圖片描述
正常請求響應流程
在這裏插入圖片描述
響應404流程
在這裏插入圖片描述
4. 編碼:編寫程序代碼

程序編碼

  1. 創建TCP併發服務器(多進程、多線程)
    從配置中讀取端口號–>將端口號寫入配置文件configure中,創建服務器時從配置文件中讀取端口號。(在啓動服務器時添加-b選項使得服務器工作在守護進程模式)
  int sockfd = socket(AF_INET,SOCK_STREAM,0);
  if(-1 == sockfd){
	perror("socket");
	return -1;
  }
  struct sockaddr_in server_addr;
  server_addr.sin_famlily = AF_INET;
  server_addr.sin_port = htons(8080)
  server_addr.sin_addr.s_addr = INADDR_ANY;

  if(bind(sockfd,(struct sockaddr*)&server_addr,
		sizeof(server_addr)) == -1){
	perror("bind");
	return -1;
  }
  listen(sockfd,10);
  
  //準備和客戶端通信的socket套接字
  int client_fd;
  struct sockaddr_in client_addr;
  socklen_t len = sizeof(client_addr);

  client_fd = accept(sockfd,&client_addr,&len);

  //創建子進程fork
  //創建子線程pthread_create
  char buf[1024]={0};
  read(client_fd,buf,1024);
  puts(buf);//客戶端發來的請求信息
  1. 接收客戶端請求,打印請求數據,瞭解瀏覽器發來的請求數據包的內容。
  2. 解析請求數據包,保存必要數據
typedef struct{
   char method[12];//請求方法,GET 
   char path[128]; //請求文件,http、jpg..
   char protocol[20];//請求協議版本,HTTP/1.1
}request_t;
  1. 創建響應頭結構體
typedef struct{
   int status;//狀態碼 200,404
   char protocol;//協議版本,HTTP/1.1
   char file_type[32];//類型信息
}response_t

  1. 從服務器目錄(www)查找請求文件是否存在,存在則返回status=200,否則status=404.
  2. 構建響應頭
  協議版本:與請求行獲取的協議版本一致
  類型信息:根據請求的文件後綴匹配
  eg:
  如果客戶請求是html文件,類型信息爲"text/html"
  同理支持如下類型:
  *.html 	--> "text/html"
  *.jpg/*.jpeg 	--> "image/jpeg"
  *.png 	--> "image/png"
  *.gif		--> "image/gif"
  *.css 	--> "text/css" 
  ...
  1. 發送響應頭給客戶端
eg:
write("HTTP/1.1 200 OK\r\n");
write("Content-Type:text/html\r\n");
write("\r\n");
  1. 發送請求的文件
/*
如果status==200,說明請求文件存在,打開文件將文件內容發送給http客戶端。
如果status==404,說明請求文件不存在,
發送"www/error.html"
*/

int fd = open("要給瀏覽器發送的文件")int bytes_read=0;
int bytes_write=0;
int buffer[1024] = {0};
char* ptr;
while(bytes_read = read(fd,buffer,1024)){
   if(bytes_read == -1){break;}
   else if(bytes_read > 0){
  	ptr = buffer;
	while(bytes_write =
		write(client_fd,ptr,bytes_read)){
	   if(bytes_write == bytes_read){//寫完
 	   	break; 
	   }
   	   else{//只寫一部分
 	      ptr += bytes_write
	      bytes_read -= bytes_write;
	   }
	}
   }
}
  1. 關閉連接

項目實例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章