1. 程式人生 > >【Linux】深入理解HTTP協議

【Linux】深入理解HTTP協議

本文參考自: 原文地址

基本概念及作用
首先HTTP協議屬於應用層協議,應用層協議就是我們程式設計師自己定協議,但如果每次都自己定麻煩並且很容易出錯,所以有了一些現成的(HTTP,DNS)等,所以大多是直接拿來用就行,而應用層的作用就是雙方達成某種約定,一段按照約定的協議傳送資料,另一端按照約定來解析資料,保證接收資料的一段可以正確解析資料,這就是應用層的作用,也是HTTP協議的作用之一。
HTTP協議的格式

HTTP協議分為HTTP請求和HTTP響應

HTTP請求


說明:

  1. 第一部分為第一行,為請求行,請求行以空格分為三個區域,第一個區域叫請求方法,常見方法為POST,GET方法;第二個區域指明想要訪問放入資源(通常以路徑的形式呈現,網頁也屬於檔案)第三個區域表示HTTP協議的版本(常見1.0/1.1)
  2. 第二部分從第二行開始,一直到空行前面稱為請求報頭(Header)。每一行都代表一個特點含義,每一行格式都是name:value
  3. 第三部分為空行,目的是為了將請求正文和請求行,請求報頭分隔開(讀到空格表示請求行和請求報頭讀完)
  4. 第四部分為請求正文(Body可以為空,請求報頭中的content_length表示正文大小)
HTTP響應

說明:

  1. 第一部分為第一行,為響應行,也分為三個區域,用空格間隔,第一個區域代表協議版本;第二個區域表示狀態碼;第三個區域為狀態碼解釋
  2. 第二部分從第二行開始,一直到空格之前稱為響應報頭,每一行都代表一個特點含義,每一行格式都是name:value
  3. 第三部分為空行,目的是為了將響應正文和狀態行,響應報頭分隔開(讀到空格表示狀態行和響應報頭讀完)
  4. 第四部分為響應正文(Body可以為空,響應報頭中的content_length表示正文大小)
實現一個簡單的HTTP伺服器
   #include <unistd.h>
   #include <string.h>
   #include <sys/types.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>
   #include <stdio.h>
   
   void serviceIO(int sock)
  {
      char buf[10240];
      ssize_t s=read(sock,buf,sizeof(buf)-1);
      if(s>0){
          buf[s]=0;
          printf("%s",buf);
      }
      const char *echo="HTTP/1.1 200 OK\r\n\r\n<html><h1>hello world!</h1></html>";
      write(sock,echo,strlen(echo));
      close(sock);
  }
  
  
  int main(int argc,char *argv[])
  {
      if(argc != 3){
          printf("Usage: %s [ip] [port]\n",argv[0]);
          return 1;
      }
  
      int listen_sock=socket(AF_INET,SOCK_STREAM,0);
      if(listen_sock<0){
          perror("sock");
          return 2;
      }
  
      struct sockaddr_in local;
		local.sin_family=AF_INET;
      local.sin_port=htons(atoi(argv[2]));
      local.sin_addr.s_addr=inet_addr(argv[1]);
  
      if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))){
          perror("bind");
          return 3;
      }
  
      int s=listen(listen_sock,5);
      if(s<0){
          perror("listen");
          return 4;
      }
  
      for( ; ;){
          struct sockaddr_in client;
          socklen_t len=sizeof(client);
         int sock=accept(listen_sock,(struct sockaddr*)&client,&len);
          if(sock<0){
              perror("accept");
              continue;
          }
          printf("get a new link [%s:%d]...!\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
 
         serviceIO(sock);
      }
      return 0;
  }

首先的關閉防火牆:service iptables stop

執行伺服器


在瀏覽器上輸入自己的ip地址