全文概要:

  • 1、HTTP概念:
  • 2、HTTP协议格式:
      • 2.0、文字描述:
      • 2.0、结构图说明:
      • 2.0、举例说明(图):
    • 2.1、首行-请求行(请求方法 ,URL(URI),协议版本\r\n)
      • 2.1.1、请求方法:——对请求的描述
      • 2.1.2、URL:——网址--同一资源定位符--用于定位网络中某个主机上的某个资源
      • 2.1.3、协议版本:0.9 ,1.0 ,1.1 ,2.0
    • 2.2、首行—响应行:协议版本、响应状态码、状态码描述\r\n
      • 2.2.1、协议版本(见2.1.3)
      • 2.2.2、响应状态码——直观向客户端反馈处理结果
      • 2.2.3、状态码描述——就是状态码的文字描述;
    • 2.3、头部——关于请求或响应或者正文的关键描述字段;
    • 2.4、空行:\r\n
    • 2.5、正文;
  • 3、http协议是一个无状态协议
  • 4、写一个HTTP的简单协议:
    • 4.1、简单的http服务器搭建:
    • 4.2、代码实现:

1、HTTP概念:

  • HTTP协议Hyper Text Transfer Protocol(超文本传输协议)的缩写,是一个简单的请求-响应协议,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议;
  • HTTP是基于TCP/IP通信协议来传递数据;

TCP不熟悉的可以看看,这个|:

——————————————下面连接:
TCP看了都会系列,点我。
——————————————上面连接|

  • HTTP默认端口号为80,但是也可以改为其他端口;

https就是对http进行了加密,提升了安全性;

2、HTTP协议格式:

2.0、文字描述:

http协议格式:http数据结构、http协议实现
首行:请求行、响应行(对于请求与响应的关键描述)
头部:对于请求或者响应或者正文的描述;
由一个个键值对组成key: val,每个键值对以\r\n结尾;
空行:\r\n,间隔头部与正文;\r\n\r\n——头部结尾;
正文:客户端提交给服务端,或者服务端响应给客户端的数据;

2.0、结构图说明:

2.0、举例说明(图):

下图备注:,为使图片内容可以说明情况即可,头部和正文有部分被删除;

2.1、首行-请求行(请求方法 ,URL(URI),协议版本\r\n)

2.1.1、请求方法:——对请求的描述

GET:从服务区获取实体资源,请求没有正文,但是也可以提交数据,但是提交的数据没有在正文中而是在URL中;
1.GET提交数据是不安全。
2.URL长度有限制。(4kb)数据有限制,正文没有限制;

HEAD:功能与GET类似,但是不要正文实体;
POST:向服务端提交数据;数据在正文中;

  • HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
  • HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

2.1.2、URL:——网址–同一资源定位符–用于定位网络中某个主机上的某个资源

(URI:同一资源标识符)

组成:协议名称://用户名:密码@域名:端口/资源路径?查询字符串
https://user:pass@www.baidu.com:80/s?ie=utf-8&wd=ASCII#ch
域名:服务器别名–最终访问服务器需要经过域名解析得到服务器IP。
/资源路径:这个路径是一个相对根目录。
?查询字符串:提交给服务器的数据,由一个个key=val形式键值对组成,键值对之间以&符号间隔;
#跳转到ch字符串处;

  • urlencode:编码–用户请求的资源路径,或者查询或者查询字符串中存在特殊字符,则有可能与url中的特殊字符冲突;

  • urldecode:解码遇到%则认为紧随其后的两个字符进行了编码,将这两个字符转换为数字,第一个数字左移4位加上第二个数字。

2.1.3、协议版本:0.9 ,1.0 ,1.1 ,2.0

0.9:最早期的版本,只支持GET方法,并且协议还没有当前的规范,只支持超文本数据传输。

1.0:规范了http协议格式,并且新增支持GET、HEAD、POST请求方法,支持各种多媒体资源传输,简单的缓存控制。
1.1:更多的是对1.0版本进行性能的优化,支持了更多请求方法以及特性(支持长连接,更加完善缓存控制,分块传输…)
2.0:因为http协议的庞大冗余,因此2.0不是新增特性,而是重定义http协议;
(1).使用二进制数据传输;
(2).支持主动推送;
(3).多路复用服务器进行长连接响应,不需要按序进行;(那个准备好发那个,无顺序);

  • 0.9只支持GET方法;
  • 1.0规范了协议格式,支持了更多请求方法,支持多媒体资源传输;但是对性能没有更多改进,因此
  • 1.1针对传输性能进行大量改进,比如支持长连接,更加完善缓存控制。。。。但是依然存在缺陷,比如管线化传输的队头阻塞问题;
  • 2.0因为1.1过于冗余庞大,因此不适合新增而重新定义,2.0采用二进制数据传输,支持服务器推送依赖数据,长连接响应无需按序,解决了队头阻塞问题;

Connection:用于控制长连接的关闭打开状态close/keep-alive;

2.2、首行—响应行:协议版本、响应状态码、状态码描述\r\n

2.2.1、协议版本(见2.1.3)

2.2.2、响应状态码——直观向客户端反馈处理结果

1xx:一些描述信息;101-协议切换状态码
2xx:表示本次请求正确处理;200
3xx:重定向-表示本次请求的资源移动到了新的连接处,但是原链接依然可用。www.image.com/img/flower.jpgwww.image.com/img/flower/rose.jpg301    302
4xx:表示客户端错误;404
5xx:表示服务器错误;502-代理服务器未收到正确响应;504-超时

HTTP响应状态码

2.2.3、状态码描述——就是状态码的文字描述;

2.3、头部——关于请求或响应或者正文的关键描述字段;

    组成:key: val\r\nkey: val\r\n...

典型的头部字段:
Connection:长短连接控制:keep-alive/close;
Referer:记录本次请求的来源链接;
Content-Type:用于表示正文数据格式;
Content-Length:用于表示正文的长度——http解决粘包问题
Location:用于指定重定向的新连接地址,与3xx搭配使用
Cookiesession:涉及的头部字段请求头Cookie,响应头Set-Cookie

2.4、空行:\r\n

是头部最后一个字段的结尾\r\n组成连续的\r\n\r\n作为特殊标志,作为http头部结束的标志;

2.5、正文;

完;

3、http协议是一个无状态协议

 1.一个客户端登录之后,服务端验证登录,成功后,通过Set-Cookie字段设置Cookie信息(用户信息、状态。。。)返回给客户端2.客户端收到响应后,将Set-Cookie字段的Cookie信息保存下来,下次请求从Cookie文件中读取Cookie信息,通过Cookie字段发送给服务器;Cookie是一个维护http通信状态的技术——但是存在安全隐患解决方案:sessionsession是服务端针对每个客户端所建立的会话,当客户端登录成功后,创建会话,在会画中记录客户端用户信息以及状态。。。,通过Set-Cookie字段将session_id返回给给客户端;用户的隐私信息一直保存在服务器防止泄露;

Cookie和session的区别:
Cookie是维护http通信转状态的技术,将关键信息保存在客户端,每次请求服务器时,读取出来发送给客户端(存在安全隐患)
session是解决Cookie安全隐患的技术,将关键信息保存在服务器,将session_id发送给客户端,作为Cookie保存起来,往后请求传输session_id即可,解决了Cookie泄密的风险;

4、写一个HTTP的简单协议:

  • http是一个应用层协议,只是应用程序如何沟通的一种数据格式约定,在传输层是基于tcp实现的;

  • http客户端实际上就是一个tcp客户端,http服务器实际上就是一个tcp服务器只不过http客户端与服务端的通信用的是http协议来约定数据格式而已;

4.1、简单的http服务器搭建:

1.搭建tcp服务端
2.获取新建连接;
3.使用新建连接,等待接受数据(http协议的请求数据)
4.接受过程:先接收http头部,解析头部-Content-Length确定正文长度;
5.接受指定长度的正文;
6.根据请求方法以及资源路径确定客户端的请求目的
7.进行具体对应的业务处理
8.组织http协议格式的响应数据,对客户端进行回复;
9.如果是短连接,则直接关闭套接字,如果是长连接,则继续等待接受数据
//回复数据:
<html><body><h1>Hello Me</h1></body></html>

4.2、代码实现:

实现后运行代码+ip+端口号
然后在网页中直接搜索ip和端口,即可看到效果;

//头文件在底下:
1 #include"tcpsocket.hpp"
2
3 int main(int argc,char *argv[]){4 //通过程序运行参数指定服务端要绑定的地址信息
5 // ./tcp_srv 192.168.106.133 9050
6     if(argc!=3){7     std::cout<<"usage: ./tcp_srv 192.168.106.133 9050"<<std::endl;
8     return -1;
9     }
10     std::string srvip=argv[1];
11     uint16_t srvport=std::stoi(argv[2]);
12     TcpSocket lst_sock;//监听套接字
13     //1.创建套接字
14     CHECK_RET(lst_sock.Socket());
15     //2.绑定地址信息
16     CHECK_RET(lst_sock.Bind(srvip,srvport));
17     //3.开始监听
18     CHECK_RET(lst_sock.Listen());
19     while(1){20     //4.获取新建连接
21         TcpSocket clisock;
22         std::string cliip;
23         uint16_t cliport;
24         bool ret=lst_sock.Accept(&clisock,&cliip,&cliport);
25         if(ret==false){26             //clisock.Close();
27             continue;
28         }
29         std::string buf;
30         clisock.Recv(&buf);
31         std::cout<<"request:["<<buf<<"]\n";
32
33         std::string body;
34         body="<html><body><h1>Hello Me</h1></body></html>";
35         std::stringstream ss;
36         ss<<"HTTP/1.1 200 OK\r\n";
37         ss<<"Connection: close\r\n";
38         ss<<"Content-Length: "<<body.size()<<"\r\n";
39         ss<<"Content_type: application/octet-stream\r\n";//下载
40         //ss<<"Content_type: test/html\r\n";//html展示
41         ss<<"\r\n";
42         ss<<body;
43         clisock.Send(ss.str());
44         clisock.Close();
45     }
46     //6.关闭套接字
47     lst_sock.Close();
48     return 0;
49 }

头文件tcpsocket.hpp

头文件用tcp,具体看一看:
TCP具体了解

#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define CHECK_RET(q) if((q)==false){return -1;}
#define LISTEN_BACKLOG 5
class TcpSocket{private:int _sockfd;public:TcpSocket():_sockfd(-1){}bool Socket() {_sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (_sockfd < 0) {perror("socket error");return false;}return true;}bool Bind(const std::string &ip, const uint16_t port){sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(&ip[0]);socklen_t len = sizeof(sockaddr_in);int ret = bind(_sockfd, (sockaddr*)&addr, len);if (ret < 0) {perror("bind error");return false;}return true;}bool Listen(int backlog = LISTEN_BACKLOG) {//listen(描述符,同一时间连接数)int ret = listen(_sockfd, backlog);if (ret < 0) {perror("listen error");return false;}return true;}bool Connect(const std::string &ip,const int port) {sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(&ip[0]);socklen_t len = sizeof(sockaddr_in);//connect(描述符,服务端地址, 地址长度)int ret = connect(_sockfd, (sockaddr*)&addr, len);if (ret < 0) {perror("connect error");return false;}return true;}bool Accept(TcpSocket *sock, std::string *ip = NULL, uint16_t *port = NULL) {//int accept(监听套接字, 回去客户端地址, 长度)sockaddr_in addr;socklen_t len = sizeof(sockaddr_in);int newfd = accept(_sockfd,(sockaddr*)&addr,&len);if (newfd < 0) {perror("accept error");return false;}sock->_sockfd = newfd;if (ip != NULL) {*ip = inet_ntoa(addr.sin_addr);}if (port != NULL) {*port = ntohs(addr.sin_port);}return true;}bool Recv(std::string *buf) {//int recv(描述符,空间,数据长度,标志位)//返回值:实际获取大小, 0-连接断开; -1-出错了char tmp[4096] = {0};int ret = recv(_sockfd, tmp, 4096, 0);if (ret < 0) {perror("recv error");return false;}else if (ret == 0) {printf("peer shutdown");return false;}buf->assign(tmp, ret);return true;}bool Send(const std::string &data) {//int send(描述符,数据,长度,标志位)int total = 0;while(total < data.size()) {int ret = send(_sockfd, &data[0] + total, data.size() - total, 0);if (ret < 0) {perror("send error");return false;}total += ret;}return true;}bool Close() {if (_sockfd != -1) {close(_sockfd);}return true;}
};

HTTP 细到无法直视相关推荐

  1. 细数Qt开发的各种坑(欢迎围观)

    1:Qt的版本多到你数都数不清,多到你开始怀疑人生.从4.6开始到5.8,从MSVC编译器到MINGW编译器,从32位到64位,从Windows到Linux到MAC.MSVC版本还必须安装对应的VS2 ...

  2. 细分化的SaaS是双刃剑:解读今年云计算趋势(5)

    本文是原创,首发于微信公众号『 Moehoo猛虎 』 [前导文章]<2017年预测:秉持客户至上理念的企业将启动云计算的第二个十年>(<Predictions 2017: Custo ...

  3. 利用GridView显示主细表并一次编辑明细表所有数据的例子

    全部代码如下: ASPX: <%@ Page Language="C#" ValidateRequest="false" AutoEventWireup= ...

  4. 怼完Sophia怼深度学习!细数完大神Yann LeCun 这些年怼过的N件事,原来顶级高手是这样怼人的...

    图片来源:PCmag.com 十多个小时前,深度学习大神Yann LeCun语出惊人,他宣布放弃"深度学习"这个词.因为媒体对这个词的炒作言过其实,混淆了大家真正的工作,而&quo ...

  5. 细数二十世纪最伟大的10大算法

    导读:作者July总结了一篇关于计算方法的文章< 细数二十世纪最伟大的10大算法 >. 一.1946 蒙特卡洛方法 [1946: John von Neumann, Stan Ulam, ...

  6. 全网最细 | 21张图带你领略集合的线程不安全

    来源 | 悟空聊架构(ID:PassJava666) 本篇主要内容如下: 本篇主要内容 本篇所有示例代码已更新到 我的Github 本篇文章已收纳到我的Java在线文档 集合,准备团战 一.线程不安全 ...

  7. TM:宿主-细菌界面的MicroRNA:宿主防御或细菌攻击

    文章目录 TM:宿主-细菌界面的MicroRNAs:宿主防御或细菌攻击 日报 摘要 图1. MiRNAs在感染过程中起着多方面的作用,控制着多个宿主细胞的功能. 图2. 微RNA对细菌性病原体感染的调 ...

  8. R语言logistic回归、判别分析(LDA)、多元自适应样条回归MARS分析案例:分析乳腺癌数据集明确细针穿刺肿瘤活检结果

    R语言logistic回归.判别分析(LDA).多元自适应样条回归MARS分析案例:分析乳腺癌数据集明确细针穿刺肿瘤活检结果 目录

  9. 从数据类型 nvarchar 转换为 bigint 时出错_JavaScript数据类型的一些细节点

    ▲ 点击上方蓝字关注我 ▲文 / 景朝霞来源公号 / 朝霞的光影笔记ID / zhaoxiajingjing图 / 自己画 目录JS数据类型的一些细节点0 / JS 中的数据类型的一些细节点(1)JS ...

最新文章

  1. 体验Remix——安卓电脑
  2. Mono 把 .NET 应用程序移植到 Linux
  3. 文件创建与文件格式的修改
  4. php 7.1.5,Centos 7平滑无缝更新PHP7.1.0到PHP 7.1.5
  5. Redis 常用操作命令
  6. free mybatis 不生效_关于 Mybatis 设置懒加载无效的问题
  7. SAP官网发布的react教程
  8. mahout贝叶斯算法开发思路(拓展篇)1
  9. 黄轩成为QQ阅读新代言人 变身“队长”号召网友 “组队读书”
  10. STL_算法_元素计数(count、count_if)
  11. 云端战争是一场马拉松,未来格局不会一家独大
  12. 第2.01节 发布版本vs源码编译
  13. 在昆山的日子终于要结束了
  14. 快讯丨阿里云洛神云网络论文再次入选全球顶会SIGCOMM
  15. Eclipse完美安装Emmet插件
  16. (转)《C++ Qt 编程视频教程》(C++ Qt Programming)[MP4]
  17. “Chart“ 图表控件基本操作
  18. 瑞星企业防毒2010网络版(一)管理中心与客户端部署
  19. A Cleaned, Hypernymed, Image Alt-text Dataset For Automatic Image CaptioningTransformer
  20. 【叶神中级】四篇-3.页面访问

热门文章

  1. 传统ERP和SaaS ERP区别在哪里?
  2. 值得收藏fNIRS功能近红外数据处理工具包盘点
  3. 非零基础自学Java (老师:韩顺平) 第10章 面向对象编程(高级部分) 10.6 抽象类
  4. 2021年中国轮式拖拉机供需现状及竞争格局分析,中国一拖市占率接近20%「图」
  5. [转载] 通用版 联想金钥匙/联想工具包
  6. C++之标准错误流(cerr)和标准日志流(clog)
  7. 诚之和:5个目前最热门岗位的IT岗位,你是哪个?
  8. 乐视三合一摄像头和kinect_乐视三合一摄像头体验:识别准确 应用丰富
  9. HDU1237 简单计算器【堆栈】
  10. 【招实习】web前端实习生