HTTP详解及代码实现

news2025/1/16 6:52:36

HTTP详解及代码实现

  • HTTP
    • 超文本
    • 传输
    • 协议
  • URL简述
  • 状态码
    • 常见的状态码
  • 请求方法
  • 请求报文
  • 响应报文
  • HTTP常见的Header
  • HTTP服务器代码

HTTP

  HTTP的也称为超文本传输协议。解释HTTP我们可以将其分为三个部分来解释:超文本,传输,协议。

超文本

  加粗样式超文本从字面意思就是超越了文本。在计算机发展初期,计算机只能传输使用文本数据,随着技术发展,出现了图片,视频,音频,超链接等,这些数据就可以统称为超文本

传输

  传输这个词从字面上很好理解,没有什么需要介绍的,事实也是如此。http中的传输意味着数据需要由发送方发送到接收方,这是废话,但是真正需要我们注意的是,HTTP是在两点之间传输的
  那可以实现多点之间传输吗?HTTP是基于TCP的,TCP是只能两点之间传输数据的。所以HTTP也只能是两点之间传输的。
  但是HTTP3.0是基于UDP的啊,可以多点传输吗?对于HTTP/3.0(基于QUIC),虽然它是基于UDP的,但它主要是为了解决传统TCP在性能上的一些限制而设计的,并不是为了直接支持多点传输。

协议

  协议这个词在我们的印象里面就是规则,在计算机世界里面,就是用来约束某些行为的规则。它是用计算机能够理解的语言,确立的一种计算机之间进行交流通信的一种规范,以及相关的控制和错误处理方式。


  所以HTTP是什么呢? 总结一下,就是在计算机世界里面,用来在两点之间传输图片,音频,视频,超链接等超文本数据的一种约定和规范。

URL简述

URL也叫做统一资源定位器,用来唯一定位全网中的资源。可以认为有了它就能够没有歧义的直接在网络中找到相应的资源。

https://editor.csdn.net/md?not_checkout=1&spm=1010.2135.3001.5352&articleId=137425440

上面这一串就是我当前写这篇博客的URL(当然你没有账号密码访问不了)。

  • https:// :这是协议名称,有http和https可选。
  • editor.csdn.net/ : 这是资源所在的服务器地址,也就是域名。
  • md : 这是资源的路径名。
  • ? : 这个是分割开资源路径名和查询参数的分隔符,**#**也有分隔的作用,不过上面URL中没有体现。
  • spm=1010.2135.3001.5352&articleId=137425440 : 这个是查询参数,用&分割开来,这些参数由客户端给服务端,用来指定资源。
  • # : 上面URL中没有体现这个。#后面是片段标识符id, 浏览器在加载该URL时会滚动到页面中对应的片段位置。

状态码

  HTTP的状态码是存在于响应报文中的。
它有以下五类:

  • 1** : 表示请求正在被处理,是一种中间状态。
  • 2** :表示请求成功被处理。
  • 3** :重定向状态码,这里的重定向指的是当前请求资源的位置发生变动,需要使用新的URL去请求新的资源。
  • 4** : 客户端的请求报文有误,服务端无法处理请求。
  • 5** : 服务端在处理请求时内部出现的问题导致无法正常处理请求。

常见的状态码

  • 200:请求成功,响应的头部会有body数据。
  • 204:请求成功,响应的头部没有body数据。
  • 301:永久重定向,请求的资源已经不存在了,需要使用新的URL请求资源。
  • 302:临时重定向,请求的资源还在,但是需要暂时的访问新的URL。
  • 304:这个是服务端告诉客户端,资源没有修改,浏览器本地缓存的资源依旧可以使用,重定向到本地资源。
  • 400:笼统的表示客户端发送的报文有误。
  • 403:服务器禁止访问,客户端并没有错误。
  • 404:在服务端中没有找到相应的资源或是资源不存在。
  • 500:笼统的表示服务端发生了错误。
  • 501:客户端请求的功能还不支持。
  • 502:通常是服务器作为网关或者代理的时候返回的状态码,表示自己没有问题,但是发送给后端服务器时发生了错误。
  • 503:服务器繁忙,暂时无法响应客户端。

请求方法

  出现在请求报文中,用来说明使用什么样的方法请求资源。
在这里插入图片描述

请求报文

  这是HTTP请求资源时发送的报文。
在这里插入图片描述
在这里插入图片描述
  首行包括:请求方法 + URL + HTTP版本号
在这里插入图片描述
  首行下面的就是请求头部,使用key:value的格式,简单且利于理解,每一对key:value占据一行,行末使用\r\n回车换行来分割每一对key:value。
  头部末尾空出一行来将头部和body分割开来。

在这里插入图片描述
  这是Body,可以发送一些数据来指定资源或者对指定资源做出处理,允许为空,若不为空,头部会使用Content-Length来表示Body长度。
  大家或许发现了Body中的数据和URL中?后面的参数很像,这并不是偶然。他们两个的作用都是为了获取指定资源或是对指定的资源做出处理,如果请求方法为POST,则参数在Body中,如果请求方法为GET,则参数在URL中,具体细节本文不做展开解释。当然Body中不仅仅局限于传递参数的作用。

响应报文

  响应报文是服务端用来对客户端请求的响应的。
在这里插入图片描述

  • 首行:版本号 + 状态码 + 状态码解释
  • 响应头部:跟请求头部一样使用key:value的格式。
  • Body:如果有Body,则Body和头部之间会有一个空行(\r\n),上图中的Body里面就是一个html代码,向客户端返回了一个html页面。

HTTP常见的Header

  • Host:请求报文中。用于指明请求的服务器的域名。
  • Connection:请求和响应报文中都有。用于说明是否使用长连接,如果使用,则设为 keep-alive。如果不使用长连接,也就是使用短连接,则设为:clone
  • Content-Type:请求报文和响应报文都有。其中的value是Body数据的长度。Header和Body的区分是通过一个空行实现的,有了Content-Type字段,也就可以确定了Body的界限了。
  • Content-Type:响应报文中。用来告诉客户端返回的数据是什么格式的。
  • Accept-Type:请求报文中,用来告诉服务端自己能够接受什么类型的。
  • Content-Encoding:响应报文。用来告诉服务器返回的数据使用了什么压缩格式。
  • Accept-Encoding:请求报文:用来告诉服务端自己能够接受什么压缩格式。
  • Cookie: 请求报文和响应报文都有。用于存储客户端的少量信息. 通常用于实现会话(session)的功能;
  • Location:响应报文中。当状态码为3**时,说明为重定向,Location字段就是指明了重定向的位置,可以为URL外部资源,也可以指向本地资源(比如304)。
  • Referer: 当前页面是从哪个页面跳转过来的;

HTTP服务器代码

// http.cpp
#include <iostream>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <jsoncpp/json/json.h>
#include <fstream>
#include <stdio.h>
#include <string>
#include <fstream>

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define ROOT "./wwwroot"
#define HOMEPAGE "a.html"

#include "Util.hpp"

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "You should " << argv[0] << " ip port\n";
        return 1;
    }

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        std::cout << "Fail to sock: " << strerror(errno) << std::endl;
        return 2;
    }

    int opt = 1;
    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]);

    int bind_flag = bind(sock, (struct sockaddr *)&local, sizeof(local));
    if (bind_flag < 0
    {
        std::cout << "Fail to bind: " << strerror(errno) << std::endl;
        return 3;
    }

    int listen_flag = listen(sock, 10);
    if (listen_flag < 0)
    {
        std::cout << "Fail to listen: " << strerror(errno) << std::endl;
        return 4;
    }

    // Start Server
    while (true)
    {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int client_sock = accept(sock, (struct sockaddr *)&client_addr, &client_len);
        if (client_sock < 0)
        {
            std::cout << "Fail to accept: " << strerror(errno) << std::endl;
            continue;
        }

        // char input_buffer[1024 * 10] = {0};
        // ssize_t input_size = read(client_sock, input_buffer, sizeof(input_buffer) - 1);
        // if (input_size < 0)
        // {
        //     std::cout << "Fail to read: " << strerror(errno) << std::endl;
        //     close(client_sock);
        //     continue;
        // }

        // char Server_buffer[1024 * 10] = {0};
        // std::cout << "[client request] " << input_buffer << std::endl;

        // Json::Value root;
        // int fd = open("../a.html", O_RDONLY);
        // const char *buf[1024 * 10];
        // read(fd, buf, sizeof(buf));
        // root["a"] = buf;
        // //Json::StyledWriter writer; // 这样会竖式的表示出来,便于调试
        // Json::FastWriter writer; // 这样会横式的表示出来
        // std::string s = writer.write(root);

        // const char *hello = "<br><br><br><br><br><h1>          你好你好!!我是汤环!!!</h1>";

        // sprintf(Server_buffer, "HTTP/1.0 200 OK\nConnection: keep-alive\nContent-Length: %lu\n\n%s", sizeof(hello), hello);

        char buffer[10240];
        ssize_t s = recv(client_sock, buffer, sizeof(buffer) - 1, 0);
        if (s > 0)
        {
            buffer[s] = 0;
            std::cout << buffer << "--------------------\n"
                      << std::endl;
        }

        std::vector<std::string> vLine;
        Util::cutString(buffer, "\r\n", &vLine);

        std::vector<std::string> vBlock;
        Util::cutString(vLine[0], " ", &vBlock);

        std::string file = vBlock[1]; // 得到客户端请求中的文件路径
        std::string target = ROOT;
        target += file;
        std::string content;
        std::ifstream in(target);

        if (!in.is_open())
        {
        }
        else
        {
            std::string line;
            while (getline(in, line))
            {
                content += line;
            }
            in.close();
            Z
        }
        std::string HttpResponse;
        if (content.empty())
            HttpResponse = "HTTP/1.1 404 NOT FOUND\r\n";
        else
            HttpResponse = "HTTP/1.1 200 OK\r\n";
        HttpResponse += "\r\n";
        HttpResponse += content;
        send(client_sock, HttpResponse.c_str(), HttpResponse.size(), 0);

        // write(client_sock, HttpResponse.c_str(), HttpResponse.size());

        close(client_sock);
    }
    return 0;
}

// Util.hpp

#pragma once

#include <iostream>
#include <vector>

class Util
{
public:
    static void cutString(const std::string &s, const std::string &sep, std::vector<std::string> *out)
    {
        std::size_t start = 0;
        while (start < s.size())
        {
            auto pos = s.find(sep, start);
            if (pos == std::string::npos)
                break;
            out->push_back(s.substr(start, pos - start));
            start += (pos - start);
            start += sep.size();
        }

        if (start < s.size())
            out->push_back(s.substr(start));
    }
};
// makefile

http:http.cpp
	g++ -o $@ $^ -std=c++11 -ljsoncpp

.PHANY:clean
clean:
	rm -f http


     😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1572704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Unet的BraTS 3d 脑肿瘤医学图像分割,从nii.gz文件中切分出2D图片数据

1、前言 3D图像分割一直是医疗领域的难题&#xff0c;在这方面nnunet已经成为了标杆&#xff0c;不过nnunet教程较少&#xff0c;本人之前跑了好久&#xff0c;一直目录报错、格式报错&#xff0c;反正哪里都是报错等等。并且&#xff0c;nnunet对于硬件的要求很高&#xff0c…

基于51单片机电子钟闹钟设计

基于51单片机电子钟闹钟设计 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff09; 功能介绍 具体功能&#xff1a; 1.LCD1602实时显示时间和闹钟时间&#xff1b; 2.可整点报时。 3.按键设置时间、闹钟。 4.使用蜂鸣器报时和响闹钟&#xff1b; ​演示视频&…

CCIE-14-MPLS_and_BGP

目录 实验条件网络拓朴 环境配置开始配置配置MPLSR1访问R6检测结果R6访问R1检测结果 实验条件 网络拓朴 环境配置 在我的资源里可以下载&#xff08;就在这篇文章的开头也可以下载&#xff09; 开始配置 R1<->R2&#xff1a;EBGP R2<->R5&#xff1a;IBGP&…

Azkaban集群模式部署详细教程

序言 Azkaban是一个用于工作流程调度和任务调度的开源工具&#xff0c;它可以帮助用户轻松地管理和监控复杂的工作流程。Azkaban的架构设计旨在提供高度可扩展性和可靠性&#xff0c;同时保持易用性和灵活性。 Azkaban的架构可以分为三个主要组件:Executor、Web Server和db数据…

FebHost:什么是土耳其.TR域名?

当前互联网高速发展,一个国家的顶级域名已成为其网络形象的重要标识。近期,土耳其国家顶级域名”.TR”引起了广泛关注,成为业界热议的话题。 作为代表土耳其共和国的国家顶级域名(ccTLD),.TR域名于1991年首次引入,由土耳其科技和信息技术部负责管理。除了常见的”.com.tr”、”…

JavaEE 初阶篇-生产者与消费者模型(线程通信)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 生产者与消费者模型概述 2.0 在生产者与消费者模型中涉及的关键概念 2.1 缓冲区 2.2 生产者 2.3 消费者 2.4 同步机制 2.5 线程间通信 3.0 实现生产者与消费者模…

【大数据存储】spark-编程

实验8-spark编程 实验&#xff1a;编写Spark应用程序&#xff08;掌握Spark应用程序的编写、编译打包和运行方法&#xff09; 1、对于两个输入文件A和B&#xff0c;编写Spark独立应用程序&#xff0c;对两个文件进行合并&#xff0c;并剔除其中重复的内容&#xff0c;得到一个…

IMU参数辨识及标定

IMU参数辨识及标定 一、标定参数分析 标定的本质是参数辨识。首先明确哪些参数可辨识&#xff0c;其次弄清怎样辨识。 参数包括陀螺仪和加速度计各自的零偏、标度因数、安装误差。 IMU需要标定的参数主要是确定性误差和随机误差&#xff0c;确定性误差主要标定bias&#xff0…

多线程学习-线程池

目录 1.线程池的作用 2.线程池的实现 3.自定义创建线程池 1.线程池的作用 当我们使用Thread的实现类来创建线程并调用start运行线程时&#xff0c;这个线程只会使用一次并且执行的任务是固定的&#xff0c;等run方法中的代码执行完之后这个线程就会变成垃圾等待被回收掉。如…

AcWing2069.网格分析

【题目链接】2069. 网络分析 - AcWing题库 输入样例1&#xff1a; 4 8 1 1 2 2 1 10 2 3 5 1 4 1 2 2 2 1 1 2 1 2 4 2 2 1输出样例1&#xff1a; 13 13 5 3 【代码及详细注释】 #include<bits/stdc.h> using namespace std; const int N1e510; int n,m,p[N],d[N]; /…

数据结构初阶:顺序表和链表

线性表 线性表 ( linear list ) 是 n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 ... 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性…

阿里巴巴蔡崇信:中国AI追赶神速,制造业霸主地位无可撼动!

快科技4月5日讯&#xff0c;阿里巴巴集团创始人兼董事长蔡崇信近日就AI技术领域及全球制造业形势发表看法。他认为&#xff0c;尽管中国在AI技术方面与美国有一定差距&#xff0c;但中国的追赶速度非常快。 AI-321 | 专注于AI工具分享的网站 AI工具集 | 人工智能工具箱 | 全球…

xss.pwnfunction-Jefff

在eval中可以直接执行命令所以直接把"直接闭合在结尾再加上一个"因为后面的"没闭和会报错 ?jeffa";alert(1);" 或 ?jeffa"-alert(1)-" -是分隔符

C++从入门到精通——类的定义及类的访问限定符和封装

类的定义及类的访问限定符和封装 前言一、类的定义类的两种定义方式成员变量命名规则的建议示例 二、类的访问限定符和封装访问限定符访问限定符说明C为什么要出现访问限定符例题 封装例题 前言 类的定义是面向对象编程中的基本概念&#xff0c;它描述了一类具有相同属性和方法…

【精品教程】护网HVV实战教程资料合集(持续更新,共20节)

以下是资料目录&#xff0c;如需下载&#xff0c;请前往星球获取&#xff1a; 01-HW介绍.zip 02-HTTP&Burp课程资料.zip 03-信息收集_3.zip 04-SQL注入漏洞_2.zip 05-命令执行漏洞.zip 06-XSS漏洞.zip 07-CSRF.zip 08-中间件漏洞.zip 09-SSRF.zip 10-XXE.zip 11-Java反序列…

Seata(分布式事务集成测试和总结)

文章目录 1.集成测试1.集成测试正常下单1.步骤2.浏览器访问 http://localhost:10008/order/save?userId666&productId1&nums1&money1003.注意事项和细节 2.集成测试模拟异常1.步骤1.com/sun/springcloud/controller/StorageController.java 休眠12s&#xff0c;模…

【项目新功能开发篇】需求分析和开发设计

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

揭秘rmallox病毒:防范、清除、恢复一步到位!

引言&#xff1a; 随着信息技术的快速发展&#xff0c;计算机病毒已成为网络安全领域的一大难题。其中&#xff0c;rmallox病毒是近年来备受关注的一种恶意软件。本文将深入探讨rmallox病毒的特性、传播途径、防范措施、清除方法以及数据恢复技巧&#xff0c;帮助读者全面了解这…

Mac苹果电脑air/pro包含m1~m3打开app显示弹框“xxx”已损坏,无法打开。您应该将它移到废纸篓

应该是保姆级教程了&#xff1a; Mac苹果电脑air/pro包含m1~m3打开app显示弹框“xxx”已损坏&#xff0c;无法打开。您应该将它移到废纸篓。 我下载的是 Sublime Text 3 for Mac中文直装版&#xff0c;https://www.32r.com/soft/38404.html 安装后打开就gg了&#xff1a; 表现…

【图论】【分类讨论】LeetCode3017按距离统计房屋对数目

本文涉及的知识点 图论 分类讨论 本题同解 【差分数组】【图论】【分类讨论】【整除以2】3017按距离统计房屋对数目 LeetCode3017按距离统计房屋对数目 给你三个 正整数 n 、x 和 y 。 在城市中&#xff0c;存在编号从 1 到 n 的房屋&#xff0c;由 n 条街道相连。对所有 …