面试题详解10-5

tcp 怎么保证数据包有序

1. 主机每次发送数据时,TCP就给每个数据包分配一个序列号并且在一个特定的时间内等待接收主机对分配的这个序列号进行确认,
2. 如果发送主机在一个特定时间内没有收到接收主机的确认,则发送主机会重传此数据包。
3. 接收主机利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,
4. 接收主机一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。

数据包编号,按正确顺序重组

tcp 和 udp 的异同

TCP是面向流的可靠数据传输连接
UDP是面向数据包的不可靠无连接

tcp 怎么保证可靠性

差错检验机制,反馈机制,重传机制,引入序号,滑动窗口协议,选择重传

tcp 中 拥塞避免 和 流量控制 机制

拥塞避免和流量控制这两种机制很像,但是流量控制是由接收方的接受能力也就是接收窗口所决定的,如果接收窗口够大,以动态调整发送窗口的大小调整发送速度
拥塞避免主要由网络情况所限制,网络情况良好,则加大发送速率,网络状态差(冗余ACK和丢包)则降低发送速率(慢启动,拥塞控制,快恢复,快重传)RENO,BBR

tcp 四次挥手的详细解释

tcp四次挥手其实可以分为两个阶段
第一:
客户端至服务器的半双工连接关闭
客户端向服务器发送FIN信号,进入FIN_WAIT1的状态,等待服务器的ACK信号 
收到服务器的ACK后,进入FIN_WAIT2
第二:
服务器至客户端的半双工连接关闭
客户端收到服务器发来的FIN后,发送ACK,并进入TIME_WAIT,等待2msl,若无异常,则客户端认为连接成功关闭
服务器收到客户端发来的ACK后,关闭连接

四次挥手之后为什么还要等待2msl

MSL是报文最大生存时间
1是因为有可能客户端发往服务器的ACK丢失,服务器并不知道客户端已经确认关闭,这时候客户端的关闭会导致服务器端无法正常关闭
2是为了保证连接中的报文都已经传递。假如短时间关闭又重新实现一个TCP还连到了同个端口上,旧连接中尚未消失的数据就会被认为是新连接的数据。

 

浏览器从输入网址到显示出网页的全过程

1.输入网址或者ip。
2.如果输入的是网址,首先要查找域名的ip地址
第一步会在浏览器缓存中查找,如果没有,转至查询系统缓存,如果还是没有,发送请求给路由器,路由器首先会在自身的缓存中查找,如果还是没有,向ips发出请求,查询ips中的dns缓存,如果还是没有递归向上查询直至根服务器。
3.浏览器与ip机器之间建立TCP连接(三次握手)(HTTP)或者在TCP上进一步建立SSL/TLS连接(HTTPS)
接下来就是发送HTTP报文啥的了
GET,POST,DELETE,PUT。

滑动窗口机制的原理和理解

GBN协议,回退N步协议,这是对停等协议的改进,因为停等协议的传输效率非常低下。每次可发送的数据为N,基数为base,小于base的数据已经发送并且确认,base是最小的已发送未确认的报文序号。在接收端同样也有一个接收窗口,(解释)GBN采用的是累计确认方式,这时候说一下选择重传机制。再说一下TCP中既不是GBN也不是SR,而是GBN和SR的综合体。
N的大小必须报文序列编号的一半,否则接收端对报文的确认可能发生混淆

Https 原理和实现

cookie和session的区别是什么

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户
cookie存在本地的上的
session是存在服务器上的
通俗讲,Cookie是访问某些网站以后在本地存储的一些网站相关的信息,下次再访问的时候减少一些步骤。另外一个更准确的 说法是:Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器,是一种在客户端保持状态的方案。
Session是存在服务器的一种用来存放用户数据的类HashTable结构。
二者都用来保持用户的状态,cookie可更改,对服务器来说并不安全,服务器常见做法有这两种
1.把session加密后放入浏览器的cookie中,浏览器重连后将加密的session发给服务器
2.cookie中存储着session的id,浏览器重连时只需要发送session_id'即可

操作系统

进程和线程的区别

进程就是包换上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文

线程是什么呢?

进程的颗粒度太大,每次都要有上下的调入,保存,调出。如果我们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不可能是一条逻辑执行的,必定有多个分支和多个程序段,就好比要实现程序A,实际分成 a,b,c等多个块组合而成。那么这里具体的执行就可能变成:
程序A得到CPU =》CPU加载上下文,开始执行程序A的a小段,然后执行A的b小段,然后再执行A的c小段,最后CPU保存A的上下文。
这里a,b,c的执行是共享了A的上下文,CPU在执行的时候没有进行上下文切换的。这 里的a,b,c就是线程,也就是说线程是共享了进程的上下文环境,的更为细小的CPU时间段。

进程切换与线程切换

Linux中五种IO模型

1)阻塞I/O(blocking I/O)
2)非阻塞I/O (nonblocking I/O)
3) I/O复用(select 和poll) (I/O multiplexing)
4)信号驱动I/O (signal driven I/O (SIGIO))
5)异步I/O (asynchronous I/O (the POSIX aio_functions))

前四种都是同步,只有最后一种才是异步IO。
同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞!
阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回!

如何实现一个同步非阻塞的请求

实现进程同步的机制有什么

信号量的实现机制

共享锁和排他锁

实现一个读写锁

设计一个无锁队列

协程的原理

数据库

索引是什么

索引(Index)是帮助MySQL高效获取数据的数据结构。

1. 索引能极大的减少存储引擎需要扫描的数据量
2. 索引可以把随机IO变成顺序IO
3. 索引可以帮助我们在进行 分组、 排序等操作时,避免使用临时表

为什么要用B+树(B+树的优缺点)

B+ 树是B- 树的变种(PLUS 版)多路绝对平衡查找树,好的时间复杂度
B+ 树扫库、表能力更强
B+ 树的磁盘读写能力更强
B+树的排序能力更强
B+ 树的查询效率更加稳定(仁者见仁、智者见智,有可能B-Tree第一次就命中了,直接返回,而B+Tree需要找到叶节点,所以查找效率不一定比B-Tree更高)
支持顺序排序,叶节点之间存在链接

B+索引和哈希索引的区别?

B-tree索引
索引是按照顺序存储的,所以,如果按照B-tree索引,可以直接返回,带顺序的数据,但这个数据只是该索引列含有的信息。因此是顺序I/O

适用于:
精确匹配
范围匹配
最左匹配
Hash索引
索引列值的哈希值+数据行指针:因此找到后还需要根据指针去找数据,造成随机I/O

适合:
精确匹配
不适合:
模糊匹配
范围匹配
不能排序
​ 1、hash索引仅满足“=”、“IN”和“<=>”查询,不能使用范围查询因为hash索引比较的是经常hash运算之后的hash值,因此只能进行等值的过滤,不能基于范围的查找,因为经过hash算法处理后的hash值的大小关系,并不能保证与处理前的hash大小关系对应。
​ 2、hash索引无法被用来进行数据的排序操作由于hash索引中存放的都是经过hash计算之后的值,而hash值的大小关系不一定与hash计算之前的值一样,所以数据库无法利用hash索引中的值进行排序操作。
​ 3、对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
​ 4、Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。
总结:哈希适用在小范围的精确查找,在列数据很大,又不需要排序,不需要模糊查询,范围查询时有用

B+树中叶子节点间的指针有什么用?

使得访问更加简单,b树的话需要不断在父节点和叶子节点之间来回移动

聚簇和非聚簇索引的区别?

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据,聚簇索引的叶子节点就是数据节点,由于聚簇索引是将数据跟索引结构放到一块,因此一个表仅有一个聚簇索引, 聚簇索引具有唯一性
非聚簇索引:非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行

非聚簇索引的查询都要回表吗?

是的

B+树 和 AVL树 B树 二叉搜索树有什么区别?

这几种各有交集但又不尽相同。
什么是二叉搜索树?
它或者是一棵空树,或者是具有下列性质的二叉树:
1.左子节点的值必定小于父节点的值
2.右子节点的值必定大于父节点的值
首先AVL树是自平衡的二叉搜索树AVL在该定义的基础上加入了平衡条件,即:某节点的左右子树的高度差小于等于1
另一种非严格自平衡的二叉搜索树是红黑树,二者使用场景略微有些不同。
AVL追求整体的绝对平衡,适合于少量插入,大量查找的应用场景(因为维护全局平衡,插入一个往往需要O(log n))
红黑树适用于一部分插入,一部分查询的场景(变色,左旋右旋场景相对少些)
B+树是对B树的拓展
一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:
1、根结点至少有两个子女;
2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;
3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ;
4、所有的叶子结点都位于同一层。
B+树对B树的改进就是:只有叶节点存数据,并且维护了两个指针,一个指向根节点另一个指向顺序叶节点的首位。
B+树还在叶子节点中加入了链接指针

为什么用Redis

因为Redis快

先说说Redis是什么吧小老弟?

Redis嘛,就是一种运行速度很快,并发很强的跑在内存上的NoSql数据库,支持键到五种数据类型的映射。

来来来,讲一讲为什么Redis这么快?

首先,采用了多路复用io阻塞机制
然后,数据结构简单,操作节省时间
最后,运行在内存中,自然速度快

简述一下Redis值的五种类型

String 整数,浮点数或者字符串
Set 集合
Zset 有序集合
Hash 散列表
List 列表

有序集合的实现方式是哪种数据结构?

跳跃表。

 

请列举几个用得到Redis的常用使用场景?

缓存,毫无疑问这是Redis当今最为人熟知的使用场景。再提升服务器性能方面非常有效;

排行榜,在使用传统的关系型数据库(mysql oracle 等)来做这个事儿,非常的麻烦,而利用Redis的SortSet(有序集合)数据结构能够简单的搞定;

计算器/限速器,利用Redis中原子性的自增操作,我们可以统计类似用户点赞数、用户访问数等,这类操作如果用MySQL,频繁的读写会带来相当大的压力;限速器比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力;

好友关系,利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同爱好之类的功能;

简单消息队列,除了Redis自身的发布/订阅模式,我们也可以利用List来实现一个队列机制,比如:到货通知、邮件发送之类的需求,不需要高可靠,但是会带来非常大的DB压力,完全可以用List来完成异步解耦;

Session共享,以PHP为例,默认Session是保存在服务器的文件中,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆;采用Redis保存Session后,无论用户落在那台机器上都能够获取到对应的Session信息。

一些频繁被访问的数据,经常被访问的数据如果放在关系型数据库,每次查询的开销都会很大,而放在redis中,因为redis是放在内存中的可以很高效的访问

 

首先我们要知道,数据库中的四基本特性(ACID)

  1. 原子性。事务要么全执行要么全不执行。比如A打钱给B,大概分为两步走,A扣钱和B收钱, 打成功的话,钱从A的账户转移到B中,失败的话还是留在A的账户中,不会扣了A的钱而B没收到。
  2. 一致性。指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性,比如A:500 B:300这个一致性状态 在A给B转了200后变成A:200 B:500的这样另一个一致性状态
  3. 隔离性。事务之间的操作互不影响,比如A给B打钱不影响C给D打钱
  4. 持久性。表示事务结束后的数据不随着外界原因导致数据丢失。今天A给B转了500块钱,在账上看到了,结果银行被抢了,B的500块钱还在。

以上四个就是事务最基本的特性了。

 

接下来在说说三种我们不希望碰到的使用场景

一。读“脏”数据。脏数据即已修改而为提交的数据。发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。这跟不可重复读类似,但是第二个事务不需要执行提交。

二。不可重复读。事务A读了某个数据后,B对该数据进行修改,A再次读取该数据的时候发现数据已经发生了变化

在上面这个例子中,事务2提交成功,它所做的修改已经可见。然而,事务1已经读取了一个其它的值。在序列化和可重复读的隔离级别中,数据库管理系统会返回旧值,即在被事务2修改之前的值。在提交读和未提交读隔离级别下,可能会返回被更新的值,这就是“不可重复读”。

四。幻读

幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。

发生的情况:没有范围锁。

 

数据库事务的隔离级别有4种,从上到下分别解决刚才提出的几种办法。由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。

 

Read uncommitted

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。

那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。
 

Read committed

读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

那怎么解决可能的不可重复读问题?Repeatable read !

 

Repeatable read

重复读,就是在开始读取数据(事务开启)时,不再允许修改操作

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

 

什么时候会出现幻读?

事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。

那怎么解决幻读问题?Serializable!

Serializable 序列化

Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

 

现在再来说说这四种隔离机制的实现手段把。

好像又得讲一下乐观锁和悲观锁。

悲观锁

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

 

 

 

 

乐观锁

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。

两种锁的使用场景

从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适

 

 

Innodb中的锁

锁 
Innodb中基本锁有以下4种: 
行级锁 
1). 共享锁(S Lock) : 允许事务读一行数据 
2). 排它锁(X Lock) : 允许事务删除或更新一行数据 
表级锁 
3). 意向共享锁(IS Lock):事务想要获得一张表中某几行的共享锁 
4). 意向排它锁(IX Lock):事务想要获得一张表中某几行的排它锁 
由于Innodb引擎支持的均为行锁,所以意向锁其实不会阻塞除全表扫描之外的任何请求

 

MVCC基本原理

基于undo日志快照,实现了MVCC机制,由于每个数据行可能存在多个版本的快照,故也称为多版本并发控制机制,实现了“一致性非锁定读”,在事务当中,读操作SELECT不需要加锁,而是读取undo日志中的最新快照。其中undo日志为用来实现事务回滚,本身没有带来额外的开销,过程如下:

基本特征

  • 每行数据都存在一个版本,每次数据更新时都更新该版本。
  • 修改时Copy出当前版本随意修改,各个事务之间无干扰。
  • 保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)

InnoDB存储引擎MVCC的实现策略

在每一行数据中额外保存两个隐藏的列:当前行创建时的版本号和删除时的版本号(可能为空,其实还有一列称为回滚指针,用于事务回滚,不在本文范畴)。这里的版本号并不是实际的时间值,而是系统版本号。每开始新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询每行记录的版本号进行比较。

每个事务又有自己的版本号,这样事务内执行CRUD操作时,就通过版本号的比较来达到数据版本控制的目的。

MVCC下InnoDB的增删查改是怎么work的

1.插入数据(insert):记录的版本号即当前事务的版本号
执行一条数据语句:insert into testmvcc values(1,"test");
假设事务id为1,那么插入后的数据行如下:

 

2、在更新操作的时候,采用的是先标记旧的那行记录为已删除,并且删除版本号是事务版本号,然后插入一行新的记录的方式。
比如,针对上面那行记录,事务Id为2 要把name字段更新
update table set name= 'new_value' where id=1;

 

3、删除操作的时候,就把事务版本号作为删除版本号。比如
delete from table where id=1;

 

4、查询操作:
从上面的描述可以看到,在查询时要符合以下两个条件的记录才能被事务查询出来:
1) 删除版本号未指定或者大于当前事务版本号,即查询事务开启后确保读取的行未被删除。(即上述事务id为2的事务查询时,依然能读取到事务id为3所删除的数据行)
2) 创建版本号 小于或者等于 当前事务版本号 ,就是说记录创建是在当前事务中(等于的情况)或者在当前事务启动之前的其他事物进行的insert。
(即事务id为2的事务只能读取到create version<=2的已提交的事务的数据集)

但由于Mysql的写操作会加排他锁(前文有讲),如果锁定了还算不算是MVCC?

所以吧,这玩意儿其实也不该叫MVCC,不管他了,爱叫啥叫啥吧,就这样。

 

 

首先我们得知道http和https是啥。

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,就是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

我们先来看看http和https之间有哪些区别吧。

  1. https需要申请CA证书(Certification Authority),事实上CA的作用是将公钥和特定实体绑定,可以这样理解:给别人认证你的密钥是你自己的。
  2. http是超文本传输协议,是明文的。https是在http的基础上加了改进,用了SSL/TLS协议。(我们一般称SSL,但实际使用中多是TLS,TLS的本质其实是SSL版本3中的一个修改版本)
  3. 二者使用端口不同,前者是80,后者是443
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

说到底,要讨论http和https,就是讨论http协议和ssl协议。

HTTP协议

无状态协议:

协议的状态是指下一次传输可以“记住”这次传输信息的能力。

http是不会为了下一次连接而维护这次连接所传输的信息,为了保证服务器内存。

比如客户获得一张网页之后关闭浏览器,然后再一次启动浏览器,再登陆该网站,但是服务器并不知道客户关闭了一次浏览器。

由于Web服务器要面对很多浏览器的并发访问,为了提高Web服务器对并发访问的处理能力,在设计HTTP协议时规定Web服务器发送HTTP应答报文和文档时,不保存发出请求的Web浏览器进程的任何状态信息。这有可能出现一个浏览器在短短几秒之内两次访问同一对象时,服务器进程不会因为已经给它发过应答报文而不接受第二期服务请求。由于Web服务器不保存发送请求的Web浏览器进程的任何信息,因此HTTP协议属于无状态协议(Stateless Protocol)。

非持续连接和持续连接:

HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。

非持续性连接:必须为每次的请求对象分配TCP的缓冲区和保持TCP变量,服务器负担大

持续性连接:一个页面(含多个资源)乃至多个页面发送给同一个用户时,能大大减少服务器的负担和减少连接建立的时间。

从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。

持续连接也不会永远保持,一般来说,经过一段时间未使用,HTTP服务求就会关闭连接。

HTTP报文:

HTTP请求报文:

  1. 请求行 (方法字段,URL字段,HTTP版本字段)
  2. 首部行(Host:主机地址,Connection:是否使用持续连接,User-agent:用户代理 ,Accept-language:接收语言,Content-Type:发送端发送的实体数据的数据类型....)
  3. 空行
  4. 实体体(GET方法时为空,使用POST时才使用)

举个报文的栗子。

方法字段主要有:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT

实际应用中使用最多的时GET和POST。所以讨论这两就好了

GET:传递参数长度受限制,因为传递的参数是直接表示在地址栏中,而特定浏览器和服务器对URL的长度是有限制的,不适合用来传递私密数据,也不适合拿来传递大量数据。一般的HTTP请求大多都是GET。

POST:POST把传递的数据封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,对数据量没有限制,也不会显示在URL中。表单的提交用的是POST。

几个常见的Content-Type:

text/html  :HTML格式
text/plain :纯文本格式      
text/xml   :XML格式

image/gif  :gif图片格式    
image/jpeg :jpg图片格式 
image/png  :png图片格式

application/xml     : XML数据格式
application/json    : JSON数据格式
application/pdf     : pdf格式  
application/msword  : Word文档格式
application/octet-stream : 二进制流数据(如文件下载)
application/x-www-form-urlencoded	POST专用:普通的表单提交默认是通过这种方式。form表单数据被编码为key/value格式发送到服务器。
application/json	POST专用:用来告诉服务端消息主体是序列化后的 JSON 字符串

HTTP Content-type 对照表​tools.jb51.net图标

 

HTTP响应报文:

  1. 状态行 (服务器HTTP协议版本,响应状态码,状态码的文本描述)
  2. 首部行 (类似请求报文)
  3. 空行
  4. 实体体

响应状态码,由3位数字组成,第一个数字定义了响应的类别

1xx:指示信息,表示请求已接收,继续处理
2xx:成功,表示请求已被成功接受,处理。
3xx:重定向
4xx:客户端错误
5xx:服务器端错误,服务器未能实现合法的请求。

简要总结一下,HTTP报文由

  1. 请求行/状态行
  2. 首部行
  3. 空行
  4. 实体体(可为空)

组成。

 

SSL协议:

在谈起ssl之前,得先了解一下加密算法

加密算法大致有三大类,对称算法,非对称算法和哈希算法。

对称加密算法的特点是加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥自然要做好保密,只能让使用的人知道,不能对外公开。常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES


在非对称加密算法中,有公钥和私钥两种密钥,其中,公钥是公开的,不需要保密,私钥由个人持有,必须妥善保管和注意保密。加密和解密使用两种不同的密钥,是它得名的原因。常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)

 

Hash算法特别的地方在于它是一种单向算法,用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。常见的Hash算法有MD2、MD4、MD5、HAVAL、SHA。

注意:文章中使用的MAC算法即是一种Hash算法,MAC=Hash(报文+MAC密钥),MAC密钥由服务器和客户端共同持有。

大致是这样的:

1.仅服务器和客户端持有MAC密钥

2.客户端发送(报文,MAC)给客户端

3.服务器即可对发送内容进行验证,查看是否有被篡改(因为MAC密钥仅二者可知,第三方修改报文后,无法生成正确的MAC)

 

ssl的特性有下:

  1. 客户鉴别
  2. 服务器鉴别
  3. 机密性
  4. 数据完整性

首先来描述一下简略的ssl创建的过程吧。、

1.握手阶段

1,客户端与服务器创建一个TCP连接
2,客户端向服务器发送hello报文,服务器向客户端发送CA证书(证书中包含服务器公钥)以证明身份
3,客户端生成一个会话密钥,用服务器所发送的公钥进行加密后发送给服务器。此时,仅有服务器与客户端均持有该密钥

2.密钥导出

由会话密钥生成加密和完整性检查的密钥,客户端和服务器均持有生成的四个密钥
1.客户端>服务器报文加密密钥
2.客户端>服务器完整性检查密钥(MAC密钥)
3.服务器>客户端报文加密密钥
4.服务器>客户端完整性检查密钥(MAC密钥)

3.数据传输

最简单的方法莫过于SSL传输数据时加密并传给TCP了,但是因为TCP是字节流的协议,这样做必须要在TCP会话结束后才能检查数传输的完整性。
为了解决该问题,将数据分割成记录,加密(记录+MAC)后传输给TCP
就算是这样,也仍有问题尚未解决。中间人仍能通过对TCP报文段中序列号的修改达成删除,调换,插入报文的目的。
为了解决该问题,SSL维护一个序号计数器,加密(记录+MAC+序号)后传输给TCP

 

接下来我们深入一下,进行更完整的描述

握手

1.客户端向服务器发送它所支持的加密算法和一个不重数
2.服务器从中选择一个对称加密算法,一个非对称加密算法和一种MAC算法,把选择以及CA证书(含公钥)以及一个服务器不重数发送给客户端
3.客户端验证证书提取服务器的公钥,随机生成一个密钥,把密钥用公钥加密后发送至服务器
4.服务器和客户端按照约定的算法,生成同刚才简略ssl中的四个密钥
5.客户端发送所有报文的MAC
6.服务器发送所有报文的MAC

之所以要进行五六步骤,因为第一个步骤中的报文是明文,为防止中间人对第一个报文进行篡改。

存在不重数是为了防止中间人进行重传攻击

连接关闭

最简单的方法当然是发送一个TCP/FIN的报文段了。
但是这样会出现截断攻击,即会话未结束时中间人假冒其中一方关闭连接
为了解决该方法,应该在类型字段中声明该记录是否用于终止SSL(虽然SSL类型是明文,但是进行了MAC鉴别)
这样,如果SSL在收到终止记录前收到了TCP/FIN报文段,就知道会有猫腻了

发布于 2019-08-28

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值