【一】什么是协议
通过udp和tcp协议大家知道,无论是以数据报还是字节流的方式去把信息传送出去,都需要将我们所有的信息转化为字符串的形式进行发送,这叫序列化,在另外一头将字符串转化为我们所需要的信息,这是反序列化。但是如何序列化及如何反序列化,这个约定就被称为应用层协议
【二】HTTP协议
虽然我们说,应用层协议是程序员自己定制的,但是作为一个cv工程师,能cv绝不自己手写。所以总有大佬带头定义了一套现成的非常好用的应用层协议,比如http(超文本传输协议)就是其中之一。
tips:超文本传输协议,顾名思义就是不仅限于文本的传输协议,还能传输音频,图片等等,是不是有的人觉得http这玩意看着有点眼熟,你没发现你的网址前缀就是这玩意吗?其实也没必要把这个玩意看成啥高大上的东西,这东西只是一个协议,协议只是一个约定,也就是意味着你底层还是需要将其转化为字符串进行传输,只不过是通过固定的格式进行传输
【三】HTTP的状态码
类别 | 原因短语 | |
1xx | Informational(信息状态码) | 接收的请求正在处理 |
2xx | Success(成功状态码) | 请求正常处理完毕 |
3xx | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4xx | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5xx | Server Error(服务器错误状态码) | 服务器请求出错 |
tips:关于HTTP状态码一些不得不说的小故事
同学们访问网页的时候,最多出现的还是404,也就是服务器无法处理请求,而不是5xx,这是为啥呢?你想想4xx是客户端错误码,客户端是使用的人的问题,而5xx是服务端,也就是服务器出了问题,抱着打死不认错的态度,当然不会说这是我服务器的错误了对吧,其实底层还有更胜一层的原因,总有一些黑客喜欢干一些破坏团结的事情,当你使用一些特殊的访问导致的服务器出错,那那些人就知道你的服务器的弱点,从而进行攻击,但是你如果返回的是4xx他们可能就不会再这个报错上多花心思了
【四】HTTP的方法
方法 | 说明 | 支持的HTTP的协议版本 |
GET | 获取资源 | 1.0/1.1 |
POST | 传输实体主体 | 1.0/1.1 |
PUT | 传输文件 | 1.0/1.1 |
HEAD | 获得报文首部 | 1.0/1.1 |
DELETE | 删除文件 | 1.0/1.1 |
OPTIONS | 询问支持方法 | 1.1 |
TRACE | 追钟路径 | 1.1 |
CONNECT | 要求用隧道协议链接代理 | 1.1 |
LINK | 建立和资源之间的关系 | 1.0 |
UNLINE | 断开连接关系 | 1.0 |
其实上面列举了这么多,最常用的其实还是get和post的方法,其他的基本上是用不到的
【五】HTTP常见的header
content-type | 数据类型(text/html) |
content-length | Body的长度 |
host | 客户端告诉服务器,所请求的资源是在哪个端口上 |
user-Agent | 声明用户的操作系统和浏览器版本信息 |
refer | 当前页面是从哪个页面跳转过来的 |
location | 搭配3xx状态码使用,告诉客户端接下来咱们去哪里 |
cookie | 在客户端存储少量信息,通常用于实现会话功能 |
【六】最简单的HTTP服务器
实现一个最简单的HTTP服务器,只在网页上输入“hello world”,只要我们按照HTTP协议构造数据,就很容易做到。、
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Usage() {printf("usage: ./server [ip] [port]\n");
}
int main(int argc, char* argv[]) {if (argc != 3) {Usage();return 1}int fd = socket(AF_INET, SOCK_STREAM, 0);//创建网络套接字if (fd < 0) {perror("socket");return 1;}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(argv[1]);addr.sin_port = htons(atoi(argv[2]));int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));//bind相关信息if (ret < 0) {perror("bind");return 1;}ret = listen(fd, 10);//设计监听状态if (ret < 0) {perror("listen");return 1;} for (;;) {struct sockaddr_in client_addr;socklen_t len;int client_fd = accept(fd, (struct sockaddr*)&client_addr, &len);//接受服务端口if (client_fd < 0) {perror("accept");continue;}char input_buf[1024 * 10] = {0}; // 用一个足够大的缓冲区直接把数据读完.ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);//读取请求if (read_size < 0) {return 1;}printf("[Request] %s", input_buf);char buf[1024] = {0};const char* hello = "<h1>hello world</h1>";sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);//写入数据write(client_fd, buf, strlen(buf));}return 0;
}
1.打开网络套接字,这一步可以理解为打开网卡,之后的链接都是从网卡中读取的
2.将网卡信息和自己的主机端口号和ip地址进行绑定
3.设置网络套接字为监听状态,监听一切访问这个ip地址的信息
4.接受信息和写入信息
tips:其中写入的信息是必须按照http协议进行构造,否则浏览器无法进行解析,其中网站用的语言为html,这个语言还是比较好学的,有想法的同学还是可以学习。