Linux网络 - HTTP协议

HTTP协议

HTTP协议是应用层协议,是程序员自己琢磨出来的。

在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协。他定义了客户端(浏览器)到服务端怎么通信,传输超文本(HTML)

客户端通过HTTP协议向服务器发送请求,服务器收到请求后做出回应。HTTP协议是一个无连接、无状态的协议。每次请求后要重新建立连接,且服务器不会保存客户端的状态信息

URL

URL就是我们所说的网址

像**/ ? :**这些字符被URL当做转义的字符使用,将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式

HTTP协议请求与响应格式

HTTP请求

首行 方法 + URL + 版本

Header:请求的属性,冒号标识键值对,每组属性用 "\r\n"分隔,遇到空行标识Header部分的结束

Body:空行后面的内容都是Body.Body允许为空字符串.如果Body存在,则在Header中会有一个Content-Length属性来标识Body的长度

HTTP应答

和请求的方式大差不差,这里有个状态码在下面讲

HTTP方法

最常见的方式就是GET和POST方法

GET方法

用途:用于请求URL的资源

POST方法

用于传输实体数据,通常用于提交表单数据,将数据提交给服务器

PUT方法(不常用)

用途:用于传输文件,将请求报文主体中的文件保存到请求URL指定的位置。

HEAD方法

用于与GET方法类似,但不返回报文主题部分,只返回响应头。用于确认URL的有效性和和资源的更新日期等

DELETE方法(不常用)

用于删除文件,和PUT方法相反

OPTIONS方法

用于查询针对请求URL指定资源支持的方法

例如 OPTIONS * HTTP/1.1 例如允许使用GET PUT方法就返回GET POST

支持的情况

复制代码
HTTP/1.1 200 OK
Allow: GET, HEAD, POST, OPTIONS
Content-Type: text/plain
Content-Length: 0
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 16 Jun 2024 09:04:44 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS//支持三个
Access-Control-Allow-Headers: Content-Type, Authorization

HTTP的状态码

常见的状态比如 200(ok) 404(Not Found) 403(Forbidden) 302(重定向) 504(Bad Getway)

|-----|-------------------|-------------------------------|
| 状态码 | 含义 | 应⽤样例 |
| 100 | Continue | 上传⼤⽂件时,服务器告诉客⼾端可以继续上传 |
| 200 | OK | 访问⽹站⾸⻚,服务器返回⽹⻚内容 |
| 201 | Created | 发布新⽂章,服务器返回⽂章创建成功的信息 |
| 204 | No Content | 删除⽂章后,服务器返回"⽆内容"表⽰操作成功 |
| 301 | Moved Permanently | ⽹站换域名后,⾃动跳转到新域名;搜索引擎更新⽹站链接时使⽤ |
| 302 | Found 或 See Other | ⽤⼾登录成功后,重定向到⽤⼾⾸⻚ |

|-----|-----------------------|------------------------------|
| 304 | Not Modified | 浏览器缓存机制,对未修改的资源返回304状态码 |
| 400 | Bad Request | 填写表单时,格式不正确导致提交失败 |
| 401 | Unauthorized | 访问需要登录的⻚⾯时,未登录或认证失败 |
| 403 | Forbidden | 尝试访问你没有权限查看的⻚⾯ |
| 404 | Not Found | 访问不存在的⽹⻚链接 |
| 500 | Internal Server Error | 服务器崩溃或数据库错误导致⻚⾯⽆法加载 |
| 502 | Bad Gateway | 使⽤代理服务器时,代理服务器⽆法从上游服务器获取有效响应 |
| 503 | Service Unavailable | 服务器维护或过载,暂时⽆法处理请求 |

重定向

HTTP状态码301(永久重定向)

当服务器返回HTTP301状态码时,表示请求的资源已经被永久移动到新的位置。

在这种情况下,服务器会在响应中添加一个Location头部,用于指定资源的新位置。这个Location头部包含了新的URL地址,浏览器会自动重定向到该地址

HTTP状态码302(临时重定向)

当服务器返回HTTP302状态码时,表示请求的资源临时被移动到新的位置。

同样地,服务器也会在响应中添加一个Location头部来指定资源的新位置。浏览器会暂时使用新的URL进行后续的请求,但不会缓存这个重定向。

cpp 复制代码
#pragma once
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/file.h>
#include<fcntl.h>
#include<string>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<vector>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>

using namespace std;

void signalhander(int sig){
    kill(-getpgrp(), SIGKILL);
}

class tcpServer{
public:
    tcpServer(uint16_t port):_port(port){
        _fd = socket(AF_INET,SOCK_STREAM,0);
    }
    tcpServer(const tcpServer&)=delete;
    tcpServer(tcpServer&&)=delete;
    tcpServer& operator=(const tcpServer&)=delete;
    tcpServer& operator=(tcpServer&&)=delete;
    void run(){
        uint16_t port = htons(_port);
        uint32_t ip;
        inet_pton(AF_INET,"0.0.0.0",&ip);
        sockaddr_in in;
        memset(&in,0,sizeof(in));
        in.sin_port=port;
        in.sin_family=AF_INET;
        in.sin_addr.s_addr = ip;
        int bindret = bind(_fd,(const sockaddr*)&in,sizeof(in));
        if(bindret==-1)throw runtime_error("bind error");

        int listenRet = listen(_fd,SOMAXCONN);
        if(listenRet==-1)throw runtime_error("listen error");

        struct sigaction sg;
        memset(&sg,0,sizeof(sg));
        sg.sa_handler=SIG_IGN;
        
        sigaction(SIGCHLD,&sg,nullptr);
        signal(SIGINT,signalhander);
        int reuse = 1;
        setsockopt(_fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));

        while(true){
            sockaddr_in in;
            socklen_t len;
            int fd = accept(_fd,(sockaddr*)&in,&len);
            pid_t id = fork();
            if(id ==0){
                if(fork()>0){
                    close(fd);
                    exit(0);
                }
                char buffer[4096];
                int ret =recv(fd,buffer,sizeof(buffer)-1,0);
                if(ret==-1){
                    if(errno==EAGAIN||errno==EINTR)continue;
                    throw runtime_error("recv error");
                }
                else if(ret==0){
                    cout<<"子进程"<<getpid()<<"的对端关闭连接"<<endl;
                    exit(0);
                }
                buffer[ret]=0;
                cout<<"子进程"<<getpid()<<"接收到:"<<buffer<<endl;

                string sendstr;
                sendstr +="HTTP/1.1 302 Found\r\nLocation: https://www.doubao.com/\r\n";
                send(fd,sendstr.c_str(),sendstr.size(),0);
                cout<<"发送"<<sendstr<<endl<<getpid()<<"关闭连接";
                close(fd);
                exit(0);
                
            }
            close(fd);
        }
    }

private:
    uint16_t _port;
    int _fd;//监听套接字
    vector<int>_fds;
};

例如这个是一个HTTP返回豆包官网的重定向服务器。大家要注意的是,必须用close关闭掉连接,否则浏览器以为数据没有接收完会一直处于转圈圈状态。直到你主动关闭连接

HTTP常见的Header

Content-Type:数据类型(text/html等) Content-Length:Body的长度

Host:客户端告知服务器,所请求的资源是在哪个主机的哪个端口上;

User-Agent:声明用户的操作系统和浏览器版本信息;

Referer:当前页面是从哪个页面跳转过来的;

Location:搭配3xx状态码使用,告诉客户端接下来要去哪里访问

Cookie:用于在客户端存储少量信息.通常用于实现会话(session)的功能

connection报头

HTTP中的Connection 字段是HTTP报文头的一部分,它主要用于控制和管理客户端与服务器之间的连接状态

核心作用管理持久连接:Connection字段还用于管理持久连接(也称为长连接)。持久连接允许客户端和服务器在请求/响应完成后不立即关闭TCP连接,以便在同一个连接上发送多个请求和接收多个响应。

持久连接(长连接)

HTTP/1.1:在HTTP/1.1协议中,默认使用持久连接。当客户端和服务器都不明确指定关闭连接时,连接将保持打开状态,以便后续的请求和响应可以复用同一个连接。

HTTP/1.0:在HTTP/1.0协议中,默认连接是非持久的。如果希望HTTP/1.0上实现持久连接,需要在请求头中显式设置Connection: keep-alive

Connection:keep-alive:表示希望保持连接以复用TCP连接。Connection:close:表示请求/响应完成后,应该关闭TcP连接。

|-----------------|-------------------------|-----------------------------------------------------------------------------------------------------|
| 字段名 | 含义 | 样例 |
| Accept | 客⼾端可接受的响应内容类型 | Accept:text/html,application/xhtml+xml,application/xm |
| Accept-Encoding | 客⼾端⽀持的数据压缩格式 | Accept-Encoding: gzip, deflate, br |
| Accept-Language | 客⼾端可接受的语⾔类型 | Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 |
| Host | 请求的主机名和端⼝号 | Host: www.example.com:8080 |
| User-Agent | 客⼾端的软件环境信息 | User-Agent: Mozilla/5.0 (Windows NT 10.0;Win64; x64) AppleWebKit/537.36 (KHTML, like |
| Cookie | 客⼾端发送给服务器的HTTP cookie信息 | Cookie: session_id=abcdefg12345; user_id=123 |
| Referer | 请求的来源URL | Referer: http://www.example.com/previous_page.html |
| Content-Type | 实体主体的媒体类型 | Content-Type: application/x-www-formurlencoded (对于表单提交) 或 Content-Type: application/json (对于JSON数据) |
| Content-Length | 实体主体的字节⼤⼩ | Content-Length: 150 |
| Authorization | 认证信息,如⽤⼾名和密码 | |
| Cache-Control | 缓存控制指令 | 请求时: Cache-Control: no-cache : Cache |

|---------------|------------------------|----------------------------------------------|
| Connection | 请求完后是关闭还是保持连接 | Connection: keep-alive 或 Connection: close |
| Date | 请求或响应的⽇期和时间 | Date: Wed, 21 Oct 2023 07:28:00 GMT |
| Location | 重定向的⽬标URL(与3xx状态码配合使⽤) | (与302状态码配合使⽤) |
| Server | 服务器类型 | Server: Apache/2.4.41 (Unix) |
| Last-Modified | 资源的最后修改时间 | Last-Modified: Wed, 21 Oct 2023 07:20:00 GMT |
| ETag | 资源的唯⼀标识符,⽤于缓存 | ETag: "3f80f-1b6-5f4e2512a4100" |
| Expires | 响应过期的⽇期和时间 | Expires: Wed, 21 Oct 2023 08:28:00 GMT |

HTTP历史及版本核心技术与时代背景

HTTP/0.9

核心技术:

仅支持GET请求方法。

仅支持纯文本传输,主要是HTML格式。

无请求和响应头信息。

时代背景:

1991年,HTTP/0.9版本作为HTTP协议的最初版本,用于传输基本的超文本HTML内容。

当时的互联网还处于起步阶段,网页内容相对简单,主要以文本为主。

HTTP/1.0

核心技术:

引入POST和HEAD请求方法。

请求和响应头信息,支持多种数据格式(MIME)

支持缓存(cache)。

状态码(status code)、多字符集支持等。

时代背景:

1996年,随着互联网的快速发展,网页内容逐渐丰富,HTTP/1.0版本应运而生。

为了满足日益增长的网络应用需求,HTTP/1.0增加了更多的功能和灵活性。

然而,HTTP/1.0的工作方式是每次TCP连接只能发送一个请求,性能上存在一定局限。

HTTP/1.1

核心技术:

引入持久连接(persistentconnection),支持管道化(pipelining)允许在单个TCP连接上进行多个请求和响应,提高了性能。

引入分块传输编码(chunked transfer encoding)

支持Host头,允许在一个IP地址上部署多个Web站点

时代背景:

1999年,随着网页加载的外部资源越来越多,HTTP/1.0的性能问题愈发突出。

HTTP/1.1通过引I入持久连接和管道化等技术,有效提高了数据传输效率。

同时,互联网应用开始呈现出多元化、复杂化的趋势,HTTP/1.1的出现满足了这些需求。

HTTP/2.0

核心技术:

多路复用(multiplexing),一个TCP连接允许多个HTTP请求。

二进制帧格式(binaryframing),优化数据传输。

头部压缩(header compression),减少传输开销。

服务器推送(serverpush),提前发送资源到客户端。

时代背景:

2015年,随着移动互联网的兴起和云计算技术的发展,网络应用对性能的要求越来越高。

HTTP/2.0通过多路复用、二进制帧格式等技术,显著提高了数据传输效率和网络性能。

同时,HTTP/2.0还支持加密传输(HTTPS),提高了数据传输的安全性。

HTTP/3.0

核心技术:

使用QUIC协议替代TCP协议,基于UDP构建的多路复用传输协议。

减少了TCP三次握手及TLS握手时间,提高了连接建立速度。

解决了TCP中的线头阻塞问题,提高了数据传输效率。

时代背景:

2022年,随着5G、物联网等技术的快速发展,网络应用对实时性、可靠性的要求越来越高。

HTTP/3.0通过使用QUIC协议,提高了连接建立速度和数据传输效率,满足了这些需求。

同时,HTTP/3.0还支持加密传输(HTTPS),保证了数据传输的安全性。

相关推荐
haluhalu.2 小时前
Linux网络编程------网络基础
网络·网络协议
ipooipoo11883 小时前
动态住宅IP的定义、核心优势与技术场景应用
网络·网络协议·tcp/ip
祁鱼鱼鱼鱼鱼3 小时前
Keepalived实验环境设定
linux·服务器·网络
滴水之功4 小时前
OpenWrt的WAN和LAN的切换
linux·网络·openwrt
莹莹学编程—成长记5 小时前
预备知识socket
网络
winfreedoms5 小时前
java-网络编程——黑马程序员学习笔记
java·网络·学习
零基础的修炼5 小时前
Linux网络---网络层
运维·服务器·网络
开开心心就好5 小时前
键盘改键工具免安装,自定义键位屏蔽误触
java·网络·windows·随机森林·计算机外设·电脑·excel
旖旎夜光6 小时前
Linux(13)(上)
linux·网络