当前位置: 首页 > news >正文

应用层协议HTTP

目录

URL

HTTP协议请求与响应格式

请求

响应

重定向

HTTP常见header

最简单的HTTP服务器

测试


HTTP(超文本传输协议)定义了客户端(如浏览器)如何和服务器进行通信的超文本

客户端向服务器发送请求,服务器收到请求,处理后给客户端返回响应。

HTTP是一个无连接无状态协议,也就是说每次都需要重新建立连接,且服务器不会保存客户端状态。

URL

我们平时使用的网址其实就是URL

有些特殊字符已经被当作特殊意义理解了,例如上文中的@,#,?

如果某个参数中需要这些特殊意义的字符,我们就需要对这些字符进行转义

转义规则如下

将需要转码的字符转为 16 进制, 然后从右到左, 取 4 位(不足 4 位直接处理), 每 2 位
做一位, 前面加上%, 编码成%XY 格式
 

HTTP协议请求与响应格式

请求

请求报头是一个键值对,我们后面会放 

最常见的是GETPOST方法 

GET:用于请求 URL 指定的资源

特性: 指定资源经服务器端解析后返回响应内容
 

如上文,就是请求'/'的资源(相对于服务器来说的)

至于请求的资源我们在后面的响应里面会写

POST:用于传输实体的主体, 通常用于提交表单数据

特性: 可以发送大量的数据给服务器, 并且数据包含在请求体中
 

当然了,以上两个最显著的区别就是,

GET方法,长度有限,并且会将我们请求的资源放在网址后面

POST方法则会隐藏我们请求的资源(不会放在网址后面)

响应

响应和请求很相似,只不过第一行改成了状态码和状态码描述

响应正文就是我们的网页代码,我们就不写了,放一个简单的hello world

状态码则是我们访问网页发送请求,后端根据请求判断网页访问的情况(不能乱填,浏览器会根据状态码判断网页是否正常)

比如说可以正常访问,网址换了(临时或永久),再或者网页关了之类的

重定向

网页重定向就是说网页换了个地址,比如说原来可能叫做4399.com,后来改名叫7k7k.com

我们有永久重定向(301)和临时重定向(其他30系的状态码)

当然了,重定向依赖的选项(键)为'Location'

我们在响应报头中填入键值对"Location:url(新的地址)",那么客户端就会根据我们时永久重定向还是临时重定向来决定是否需要缓存新的url

如果说是永久重定向,那么就会缓存新的url,每次访问原url就会直接去访问缓存的url

如果说是临时重定向则不会缓存

HTTP常见header

Content-Type: 数据类型(text/html 等)
Content-Length: Body 的长度
Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
User-Agent: 声明用户的操作系统和浏览器版本信息;
Referer: 当前页面是从哪个页面跳转过来的;
Location: 搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;
Connection:是否保持长连接(keep-alive表示希望保持,close表示请求/响应完成后关闭TCP连接)

最简单的HTTP服务器

#include <iostream>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
const int default_port = 8080;
int main()
{int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0){std::cout << "sock创建失败" << std::endl;exit(0);}struct sockaddr_in addr;addr.sin_addr.s_addr = INADDR_ANY;addr.sin_family = AF_INET;addr.sin_port = htons(default_port);//这里要记得转网络int opt=1;setsockopt(fd,SOL_SOCKET,SO_REUSEADDR |SO_REUSEPORT,&opt,sizeof(opt));int n = bind(fd, (struct sockaddr *)&addr, sizeof(addr));if (n < 0){std::cout << "bind失败:" <<strerror(errno)<< std::endl;exit(0);}n = listen(fd, 5);if (n < 0){std::cout << "listen失败" << std::endl;exit(0);}while (true){struct sockaddr_in accept_addr;socklen_t len = sizeof(accept_addr);std::cout << "准备accept" << std::endl;int sockfd = accept(fd, (struct sockaddr *)&accept_addr, &len); // 我们这里只做演示,接收完一个,返回后就关掉std::cout << "accept成功" << std::endl;if (sockfd < 0){std::cout << "accept失败" << std::endl;exit(0);}char buffer[1024];int length = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (length < 0){std::cout << "接收失败" << std::endl;exit(0);}buffer[length] = 0;printf("接收到request:\n%s\n", buffer);char outbuffer[1024];const char *hello = "<h1>hello world</h1>";snprintf(outbuffer, sizeof(outbuffer), "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);send(sockfd, outbuffer, strlen(outbuffer), 0);printf("发送响应:\n%s\n",outbuffer);close(sockfd);}close(fd);
}

测试

http://www.lqws.cn/news/456373.html

相关文章:

  • shell脚本--变量
  • GNU Octave 基础教程(2):第一个 Octave 程序
  • 碳中和时代的家电革命,从华为智选IAM看科技企业的环保担当
  • conda导出环境文件requirements.txt
  • 解决 Conda 玑境激活问题:缺少 `bin/activate` 文件的应对方法
  • react 面试题
  • 信创 CDC 实战|国产数据库的数据高速通道:OceanBase 实时入仓 StarRocks
  • flask静态资源与模板页面、模板用户登录案例
  • 服务网格安全(Istio):用零信任架构重构微服务通信安全
  • 【系统规划与管理师第二版】1.3 新一代信息技术及发展
  • 三维视频融合怎么弄?三步实现精准投射与自由修剪
  • 如何在服务器终端下载百度网盘数据
  • Spring 的IoC 和 AOP
  • Git 查询与切换分支的完整指南
  • 语音相关-浏览器的自动播放策略研究和websocket研究
  • OCR大模型,破解金融文档处理困境,从文字识别到文字理解
  • 【国产化-k8s】超混合架构-x86+arm64+欧拉+麒麟V10部署k8s1.32+kubesphere4.1
  • Ubuntu 下安装配置和调优 Oh-my-fish
  • 日志监控与日志分析工具:ELK栈、Fluentd
  • PowerShell批量处理文件名称/内容的修改
  • 局域网文件共享及检索系统
  • 云祺容灾备份系统公有云备份与恢复实操-AWS
  • Rust使用tokio(二)HTTPS相关
  • day03-微服务01
  • 商业秘密被公开后的损失计算:从法律规定到司法实践的深度解析
  • 举办骑行展览的城市需要具备哪些关键条件
  • 【vdbench】vdbench配置文件参数含义
  • 【工具使用-VScode】VScode如何设置空格和tab键显示
  • .Net Framework 4/C# 数据访问技术(ADO.NET)
  • 一些实用的chrome扩展0x02