HTTP的也称为超文本传输协议。解释HTTP我们可以将其分为三个部分来解释:超文本,传输,协议。
加粗样式超文本从字面意思就是超越了文本。在计算机发展初期,计算机只能传输使用文本数据,随着技术发展,出现了图片,视频,音频,超链接等,这些数据就可以统称为超文本。
传输这个词从字面上很好理解,没有什么需要介绍的,事实也是如此。http中的传输意味着数据需要由发送方发送到接收方,这是废话,但是真正需要我们注意的是,HTTP是在两点之间传输的。
那可以实现多点之间传输吗?HTTP是基于TCP的,TCP是只能两点之间传输数据的。所以HTTP也只能是两点之间传输的。
但是HTTP3.0是基于UDP的啊,可以多点传输吗?对于HTTP/3.0(基于QUIC),虽然它是基于UDP的,但它主要是为了解决传统TCP在性能上的一些限制而设计的,并不是为了直接支持多点传输。
协议这个词在我们的印象里面就是规则,在计算机世界里面,就是用来约束某些行为的规则。它是用计算机能够理解的语言,确立的一种计算机之间进行交流通信的一种规范,以及相关的控制和错误处理方式。
所以HTTP是什么呢? 总结一下,就是在计算机世界里面,用来在两点之间传输图片,音频,视频,超链接等超文本数据的一种约定和规范。
URL也叫做统一资源定位器,用来唯一定位全网中的资源。可以认为有了它就能够没有歧义的直接在网络中找到相应的资源。
https://editor.csdn.net/md?not_checkout=1&spm=1010.2135.3001.5352&articleId=137425440
上面这一串就是我当前写这篇博客的URL(当然你没有账号密码访问不了)。
HTTP的状态码是存在于响应报文中的。
它有以下五类:
出现在请求报文中,用来说明使用什么样的方法请求资源。

这是HTTP请求资源时发送的报文。


首行包括:请求方法 + URL + HTTP版本号

首行下面的就是请求头部,使用key:value的格式,简单且利于理解,每一对key:value占据一行,行末使用\r\n回车换行来分割每一对key:value。
头部末尾空出一行来将头部和body分割开来。

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

keep-alive。如果不使用长连接,也就是使用短连接,则设为:clone。// http.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 = "
你好你好!!我是汤环!!!
";
// 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
#include
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
😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄