Linux基础 (十六):HTTP 协议与 web 服务器

avatar
作者
猴君
阅读量:0

         本篇博客,我们将共同探索HTTP协议的工作原理,理解它是如何在客户端和服务器之间传递信息的。我们将深入研究HTTP请求和响应的结构,了解状态码、头部信息和常见的HTTP方法。同时,我们还会讨论HTTPS的安全机制,了解如何保护数据的传输安全。

目录

一、浏览器与服务器通信过程(面试)

二、HTTP 请求报头

2.1 HTTP 的请求报头结构

2.2 HTTP 的请求方法

三、HTTP 应答报头

3.1 HTTP 的应答报头结构

3.2 HTTP 的应答状态

四、Web 服务器的 C 语言实现(了解)


一、浏览器与服务器通信过程(面试)

          HTTP 协议(超文本传输协议,不仅可以传输文本文件 还可以传视频,图片,声音 是一种应用层协议,主要用于浏览器与 web 服务器通信使用,而 HTTP 协议在传输层使用的还是 TCP 协议。浏览器需要和 web 服务器三次握手建立连接后,才可以发送 HTTP 请求报文,服务器收到请求报文后,向浏览器回复 HTTP 应答报文。浏览器向服务器发起连接前,需要得到服务器的 IP 及端口。用户在浏览器中通常只输入网址(网站域名),浏览器会通过 DNS 服务查询获取到服务器的 IP 地址。对于端口来讲, 使用 HTTP 协议的程序一般默认使用 80 端口。整个过程如下图所示:

长连接:

         浏览器服务器建立连接后,如果两次以上的请求复用同一个 TCP 连接,则称之为长连接。

短连接:

         如果浏览器发送一次请求报文,服务器回复一次应答就断开连接,下次交互再重新进行三次握手建立连接,那么就被称作短连接。使用长连接显然是更好一些,可以减少网络中的 同步报文,也使得服务器的响应速度变快。

注意:

       1024以内的端口只有管理员才能使用,因此,必须切换到管理员身份。

常见的 web 服务器有:

◼ Apache: 简单、速度快、性能稳定,并可做代理服务器使用

◼ IIS(Internet Information Server):安全性、强大、灵活

◼ Nginx:小巧而高效,可以做高效的负载均衡反向代理

◼ Tomcat:技术先进、性能稳定、免费 

二、HTTP 请求报头

2.1 HTTP 的请求报头结构

       HTTP 请求报头(HTTP Request Headers)是 HTTP 请求消息的一部分,包含关于客户端、请求资源以及请求本身的附加信息。请求报头帮助服务器了解请求的性质和客户端的能力,从而做出适当的响应

HTTP 请求报文段示例:

  1. Request Line (请求行): 包含HTTP方法(如GET、POST)、请求的资源路径、HTTP版本。 
  2. Host: 指定请求的目标主机和端口(IP地址或者网站)。
  3. User-Agent: 指定发出请求的客户端软件信息。
  4. Accept: 指定客户端可处理的内容类型。
  5. Accept-Language: 指定客户端希望的语言。
  6. Accept-Encoding: 指定客户端支持的内容编码类型(压缩方法)。
  7. Connection: 指定是否需要保持连接。

2.2 HTTP 的请求方法

      HTTP 请求方法(HTTP Request Methods)是客户端用来向服务器指明所要执行的操作的。

三、HTTP 应答报头

3.1 HTTP 的应答报头结构

        HTTP 应答报头(HTTP Response Headers)是服务器在响应HTTP请求时返回的一组键值对,提供有关响应和服务器的更多信息。

  1. Status Line (状态行): 包含HTTP版本、状态码和状态描述。
  2. Server: 指定处理请求的服务器软件信息。
  3. Content-Type: 指定响应体的MIME类型。
  4. Content-Length: 指定响应体的字节长度。 

3.2 HTTP 的应答状态

        HTTP 响应状态码(HTTP Response Status Codes)是服务器在响应HTTP请求时返回的,用于指示请求的处理结果。

面试题:

  1. 一百开头是 信息
  2. 二百开头是 成功 200 OK
  3. 三百开头是 重定向
  4. 四百开头是 客户端错误 404 Not Found资源没找到 403 Forbidden
  5. 五百开头是 服务器错误

客户端的错误是:客户的请求错误,服务器无法响应。服务器的错误是:客户的请求没错误,服务器因为自身原因,现在没法提供服务。

四、Web 服务器的 C 语言实现(了解)

        Web 服务器对应的文件是 MyHttp.c,代码示例如下, 其中使用到的页面文件(.html)需要 用户自己提供,并且和程序在同一个位置:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <fcntl.h> #include <sys/stat.h>  #define DATALENGTH 1024 // 缓冲区大小 #define PATHLENGTH 128 // 文件路径长度  // 发送 HTTP 应答报头 void SendHeadData(int c, int size, int flag) {     char buff[DATALENGTH] = "HTTP/1.0 "; // HTTP 响应协议版本     if (flag)     {         strcat(buff, "200 OK\r\n"); // 成功响应状态码     }     else     {         strcat(buff, "404 Not Found\r\n"); // 文件未找到状态码     }      strcat(buff, "Server: MyWeb/1.0\r\n"); // 服务器信息     strcat(buff, "Content-Length: ");     sprintf(buff + strlen(buff), "%d", size); // 响应内容长度     strcat(buff, "\r\n");     strcat(buff, "Content-Type: text/html;charset=utf-8\r\n"); // 响应内容类型     strcat(buff, "\r\n");      send(c, buff, strlen(buff), 0); // 发送响应头 }  // 发送页面文件的内容 void SendFileData(int c, int fd) {     while (1)     {         char buff[DATALENGTH] = { 0 };         ssize_t n = read(fd, buff, DATALENGTH - 1); // 读取文件内容         if (n <= 0)         {             break;         }          send(c, buff, (size_t)n, 0); // 发送文件内容     } }  // 处理客户端的请求数据 void DealClientData(int c) {     char requestBuff[DATALENGTH] = { 0 };     int n = recv(c, requestBuff, DATALENGTH - 1, 0); // 接收客户端请求     if (n <= 0)     {         return;     }      char *file = strtok(requestBuff, " ");     file = strtok(NULL, " ");      int flag = 1;     char path[PATHLENGTH] = "."; // 程序所在位置     strcat(path, file); // 构建文件路径     int fd = open(path, O_RDONLY); // 打开文件     if (fd == -1)     {         fd = open("./404.html", O_RDONLY); // 若文件未找到,则打开 404 页面         flag = 0;     }      struct stat st;     fstat(fd, &st); // 获取文件信息      SendHeadData(c, st.st_size, flag); // 发送响应头     SendFileData(c, fd); // 发送文件内容     close(fd); // 关闭文件描述符 }  // 初始化服务器的套接字 int InitSocket() {     int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字     if(sockfd == -1) return -1;      struct sockaddr_in saddr;     memset(&saddr, 0, sizeof(saddr));     saddr.sin_family = AF_INET;     saddr.sin_port = htons(80); // 端口号设为 80     saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // IP 地址设为本地回环地址      int res = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)); // 绑定地址     if(res == -1) return -1;      res = listen(sockfd, 5); // 开始监听连接请求     if(res == -1) return -1;      return sockfd; }  int main() {     int sockfd = InitSocket();     assert(sockfd != -1);     while (1)     {         struct sockaddr_in caddr;         socklen_t len = sizeof(caddr);         int c = accept(sockfd, (struct sockaddr*)&caddr, &len); // 接受客户端连接         if (c < 0)         {             continue;         }          DealClientData(c); // 处理客户端请求         close(c); // 关闭连接     }      exit(0); }     

       上述代码实现了一个简单的Web服务器。它能够接收客户端的HTTP请求,并根据请求内容返回相应的文件内容或错误页面。服务器通过套接字监听端口80,接受客户端连接请求。当接收到请求后,根据请求内容打开对应的文件,并将文件内容作为HTTP响应返回给客户端。如果请求的文件不存在,则返回404页面。

至此,已经讲解完毕!篇幅较长,慢慢消化,以上就是全部内容!请务必掌握,创作不易,欢迎大家点赞加关注评论,您的支持是我前进最大的动力!下期再见!

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!