数据结构和算法:
物理结构和逻辑结构
1.逻辑结构(集合结构,线性结构,树形结构,图形结构)
2.物理结构一般是讲内存,顺序存储结构,链式存储结构
浅谈算法中,高斯算法从1加到100,循环的话是100次,高斯的方法只需要一次
1.推导大O阶:O(1) O(n) O(n^2) O(logn)
1.常数1取代时间所有加法常数
2.只保留最高项
3.去除项相乘的常数,去掉系数
2.O(1)data[k+1]=L->data[k]
4.将元素填入位置i处 L->data[i-1]=e
5.表长加1
删除元素: 时间复杂度都是O(n)
1.如果删除位置不合理,抛出异常
2.取出删除元素 L.data[i-1]
3.从删除位置开始遍历到最后一个位置,向前移动一个位置 L->data[k-1]=L->data[k]
4.表长减一
单链表结构和顺序存储结构的优缺点:
1.存储分配方式=>顺序存储是用一段连续的存储单元依次存储线性表的数据元素;单链表采用链式存储结构,用一组任意存储单元存放
2.时间性能=>查找 顺序结构是O(1) 单链表是O(n) ;插入和删除 顺序存储是O(n) 单链表是O(1)
3.空间性能=>顺序存储是预分配存储空间 ; 单链表不需要预分配,元素个数不受限制
1.将单链表中终端结点的指针端由空指针改为指向头结点,单循环链表,循环链表和单链表的主要差异就在于循环的判断条件上
原来是判断p->next是否为空,现在则是p->next不等于头结点,则循环未结束
2.指向终端结点的尾指针代表该循环链表
3.两条循环链表合并成一个循环链表
p=rearA->next;保存A表的头结点
rearA->next=rearB->next->next;将本是B表的第一个结点赋值给rearA->next
rearB->next=p; 将原A表的头结点赋值给rearB->next free(p)
1.双向链表就是在单链表的每个结点中,再设置一个指向其前驱结点的指针域
2.双向链表的插入操作,将s插入到p和p->next之间 , 先搞定s的前驱和后继 , 再搞定后结点的前驱 ,最后搞定前结点的后继
s->prior=p ;把p赋值给s的前驱
s->next=p->next ;把p->next赋值给s的后继
p->next->prior=s ;把s赋值给p->next的前驱
p->next =s ; 把s赋值给p的后继
3.删除结点p
p->prior->next=p->next ;把p->next赋值给p->prior的后继
p->next->prior=p->prior ;把p->prior赋值给p->next的前驱
反转链表:
1.常见方法分为迭代和递归,迭代是从头到尾,递归是从尾到头
2.设置两个指针,old和new,每一项添加在new的后面,新链表头指针指向新的链表头
3.old->next不能直接指向new,而是应该设置一个临时指针tmp,指向old->next指向的地址空间,保存原链表数据,然后old->next指向new,new往前移动到old处new=old,最后old=tmp取回数据
while(old!=null){
tmp=old->next
old->next=new
new=old
old=tmp
}
二叉链表:
1.链式存储结构.每个结点有两个孩子,设计一个数据域,两个指针域,叫做二叉链表
2.遍历二叉树
二叉树的遍历:从根结点出发,按照某种次序依次访问二叉树中的所有结点,每个结点仅被访问一次[访问和次序],对于计算机来说它只会处理线性序列
前序遍历:先访问根结点,前序遍历左子树,前序遍历右子树;中左右
中序遍历:左中右 preOrderFunc(T->lchild);printf("%c",T->data);preOrderFunc(T->rchild)
后序遍历:左右中 preOrderFunc(T->lchild);preOrderFunc(T->rchild);printf("%c",T->data);
层序遍历:一层层的遍历
前序遍历递归代码:printf("%c",T->data);preOrderFunc(T->lchild);preOrderFunc(T->rchild)
推导遍历结果:
前序abcdef(中左右) 中序cbaedf(左中右) 后序遍历结果是多少(左右中) cbefda
a
b d
c e f
中序abcdefg 后序bdcafge 前序 eacbdgf
e
a g
c f
b d
1.已知前中可以唯一确定一颗二叉树
2.已知后中可以唯一确定一棵二叉树
3.已知前后不能确定一棵二叉树
二叉树创建:
利用递归的原理,只不过在原来打印结点的地方,改成了生成结点,给结点赋值的操作
if(ch=='#'){*T=NULL;}else{malloc();(*T)->data=ch;createFunc((*T)->lchild);createFunc((*T)->rchild);}
二叉树:n个结点的有限集合,根结点的左子树和右子树组成,查找起来效率特别高
1.每个结点最多有两颗子树
2.左子树和右子树都是有顺序的,次序不能颠倒
3.即使只有一棵树,也要区分左子树和右子树
4.斜树,左斜树,右斜树,每一层只有一个结点
5.满二叉树,很完美,所有的分支结点都存在左子树,右子树,所有叶子在同一层
6.完全二叉树,按层序编号,结点位置和满二叉树一致,按层序标号不能有空档
队列:
1.队列是先进先出的线性表,FIFO,允许插入的一端叫队尾,允许删除的一端队头
2.队列的抽象数据类型
InitQueue(*Q):初始化操作 QueueLength(Q):返回队列的长度
DestroyQueue(*Q):销毁队列 ClearQueue(*Q):清空队列 QueueEmpty(Q):判断队列是否为空
GetHead(Q,*e):用e返回队列的队头元素
EnQueue(*Q,e):插入e到队列的队尾元素
DeQueue(*Q,*e):删除队列的队头元素
3.引入两个指针front指向队头元素,rear指向队尾元素的下一个位置,队列顺序存储的不足,出队列时每个元素都移动,如果不移动会有假溢出问题
4.循环队列,把队列头尾相接的顺序存储结构,解决假溢出问题
广度优先:
$oUrls=get(ROOT,$headers);
$result=array();
$queue=array();
foreach($oUrls as $u){
$result[$u]=true;
array_push($queue,$u);
while(!empty($queue)){
$v=array_pop($queue);
$temp=get($v,$headers);
foreach($temp as $j){
if(!isset($result[$j])){
echo $j."\r\n";
$result[$j]=true;
array_push($queue,$j);
}
}
}
}
var_dump($result);
哈希表查找:
1.顺序表查找:挨个比较
for(i=1;i<=n;i++){a[i]==key return}
顺序表查找的优化:
解决每次都要对i是否小于n作比较,设置一个哨兵,如果查找失败,一定会在结尾a[0]处等于key,此时返回0;免去了每次都判断是否越界
a[0]=key;i=n;while(a[i]!=key){i--}
2.有序表查找:二分法查找
1.折半查找:取中间记录的查找方法,又称为二分查找.前提是线性表中的记录必须是有序的,取中间记录作为比较对象,若关键字相等则查找成功,若小于则在左半区查找,若大于则在右半区查找
left mid right
while(lefta[mid]){left=mid+1}
else{return mid}
}return 0
3.散列表查找:存储的时候使用散列函数计算出地址,直接通过存储位置查找
1.定向查找的存储技术,通过关键字和哈希函数得到一个位置
2.不适合查找关键字相同,不适合查找范围的,对于一对一的查找最好
排序算法:
非线性比较类:
交换排序
冒泡:平均O(n^2),最坏O(n^2) 最好O(n) 空间O(1) 稳定
快速:平均O(nlogn),最坏O(n^2),平均O(nlogn),空间O(nlogn) 不稳定
插入排序
插入:平均O(n^2),最坏O(n^2) 最好O(n) 空间O(1) 稳定
希尔:平均O(n^1.3),最坏O(n^2),最好O(n),空间O(1) 不稳定
选择排序
选择:平均O(n^2),最坏O(n^2),最好O(n^2),空间O(1) 不稳定
堆 :平均O(nlogn),最坏O(nlogn),平均O(nlogn),空间O(1) 不稳定
归并排序
二路归并:平均O(nlogn),最坏O(nlogn),平均O(nlogn),空间O(1) 稳定
多路归并
线性非比较类:
计数:平均O(n+k),最坏O(n+k),最好O(n+k),空间O(n+k) 稳定
桶:平均O(n+k),最坏O(n^2),最好O(n),空间O(n+k) 稳定
基数:平均O(n*k),最坏O(n*k),最好O(n*k),空间O(n+k) 稳定
稳定:原来a在b前面,a=b,排序后a任然在b前面 冒泡,插入,归并,计数,桶,基数
不稳定:a=b,排序前a在b前面,排序后可能在后面,快速,希尔,选择,堆
冒泡排序:
1.比较相邻元素,从第一个开始较大的逐渐往后移动,后面是所有已经排好序的了
2.for{for{}},arr[j]>arr[j+1]
for($x=0;$x$arr[$y+1]){
$temp=$arr[$y];
$arr[$y]=$arr[$y+1];
$arr[$y+1]=$temp;
}
}
}
选择:
1.两层循环,假定第一层循环的i元素是最小值,
2.内层循环找出比i还小的元素,交换下他们
3.数组分成前后两个部分,前部分是排序的,后部分是无序的
4.两层循环,先假定当前循环的第一个索引为最小值,内部循环找比该索引还小的值,找到交换
function selectSort(&$arr){
$len=count($arr);
for($i=0;$i<$len;$i++){
$minIndex=$i;//假定当前i是最小值
for($j=$i+1;$j<$len;$j++){
if($arr[$j]<$arr[$minIndex]){
$minIndex=$j;
break;
}
}
$t=$arr[$i];
$arr[$i]=$arr[$minIndex];
$arr[$minIndex]=$t;
}
return $arr;
}
插入排序:
定义数组长度变量$len,使用count()函数,参数:数组
for循环数组,条件:从第二个开始,遍历数组,循环内
定义临时变量$temp,赋值当前元素
for循环数组,条件:遍历当前元素前面的所有元素
判断当前元素与它前面的元素的大小,利用临时变量,转换变量
function insert_sort($arr){
$len=count($arr);
for($i=1;$i<$len;$i++){
$temp=$arr[$i];
for($j=$i-1;$j>=0;$j--){
if($temp<$arr[$j]){
$arr[$j+1]=$arr[$j];
$arr[$j]=$temp;
}else{
break;
}
}
}
return $arr;
}
快速排序:
1.基于二分的思想
2.第一个作为基准数,左右各一个指针,同时扫描,右边先走,找到比基准数小的停下
左边再走,找到比基准数大的停下,左右交换
3.当左右相遇的时候,把当前的和基准数调换,递归调用
4.快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)
quickSort &arr,left,right
if left>right return
temp=arr[left]
i=left
j=right
while i=temp && i $heap->getTopNode()) {
$heap->setTopNode($list[$i]);
}
}
TCP:
OSI七层/五层协议:物理层,数据链路层,网络层,传输层,应用层(会话层/表示层)
数据链路层:做到封装成帧,透明传输,差错检验
数据链路层的差错检测:路由器能做到的是传输接收后如果有错误就丢掉,用的CRC循环冗余检验,不提供可靠传输
网络层:负责在不同网络之间尽力转发数据包,不负责丢失重传,也不负责顺序
查看路由表:route -n
ARP协议可以将网络层地址到任意物理地址转换,从IP地址到MAC地址转换
TTL是什么?有什么用处,通常那些工具会用到它?(ping? traceroute? ifconfig? netstat?)
1.Time To Live是生存时间的意思,就是说这个ping的数据包能在网络上存在多少时间。当我们对网络上的主机进行ping操作的时候,我们本地机器会发出一个数据包,数据包经过一定数量的路由器传送到目的主机,但是由于很多的原因,一些数据包不能正常传送到目的主机,那如果不给这些数据包一个生存时间的话,这些数据包会一直在网络上传送,导致网络开销的增大。当数据包传送到一个路由器之后,TTL就自动减1,如果减到0了还是没有传送到目的主机,那么就自动丢失。
不同操作系统发出的Ping数据包TTL值不同,不过大多为64,125,255这几种,你的ping命令返回TTL结果是64,说明此ping包没有经过路由器,你ping的是内网机器.
2.每经过一个路由就会被减去一,如果它变成0,包会被丢掉。它的主要目的是防止包在有回路的网络上死转,浪费网络资源。ping和traceroute用到它。
3.TTL的主要目的是防止包在有回路的网络上死转,因为包的TTL最终后变成0而使得此包从网上消失(此时往往路由器会送一个ICMP包回来,traceroute就是根据这个做的)
路由表是做什么用的?在linux环境中怎么来配置一条默认路由?
简: 路由表是用来决定如何将包从一个子网传送到另一个子网的,换局话说就是用来决定从一个网卡接收到的包应该送的哪一张网卡上的。在Linux上可以用“route add default gw <默认路由器IP>”来配置一条默认路由。
详: 路由表是用来决定如何将包从一个子网传送到另一个子网的,换局话说就是用来决定从一个网卡接收到的包应该送的哪一张网卡上的。路由表的每一行至少有目标网络号、netmask、到这个子网应该使用的网卡。当路由器从一个网卡接收到一个包时,它扫描路由表的每一行,用里面的netmask和包里的目标IP地址做并逻辑运算(&)找出目标网络号,如果此网络号和这一行里的网络号相同就将这条路由保留下来做为备用路由,如果已经有备用路由了就在这两条路由里将网络号最长的留下来,另一条丢掉,如此接着扫描下一行直到结束。如果扫描结束任没有找到任何路由,就用默认路由。确定路由后,直接将包送到对应的网卡上去。在具体的实现中,路由表可能包含更多的信息为选路由算法的细节所用。题外话:路由算法其实效率很差,而且不scalable,解决办法是使用IP交换机,比如MPLS。
在Linux上可以用“route add default gw <默认路由器IP>”来配置一条默认路由。
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排除故障?
答:测试这两台机器是否连通:从一台机器ping另一台机器,如果ping不通,用traceroute可以确定是哪个路由器不能连通,然后再找问题是在交换设备/hup/cable等。
传输层
TCP报头:
1.源端口和目的端口:各占2个字节,分别写入源端口和目的端口;
2.序列号:占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
3.确认号:占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;
4.数据偏移报头长度:占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
5.保留:占6位,保留今后使用,但目前应都位0;
6.标志位
同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
7.窗口大小:占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
8.检验和:占2字节,校验首部和数据这两部分;
9.紧急指针:占2字节,指出本报文段中的紧急数据的字节数;
10.选项:长度可变,定义一些其他的可选的参数。
TCP报文长度是由什么确定的?
MTU:最大传输单元,以太网的MTU为1500Bytes
MSS:最大分解大小,为每次TCP数据包每次传输的最大数据的分段大小,由发送端通知接收端,发送大于MTU就会被分片
TCP最小数据长度为1460Bytes
这个跟具体传输网络有关,以太网的MTU为1500字节,Internet的MTU为576字节。
MTU是网络层的传输单元,那么MSS = MTU - 20字节(IP首部) - 20字节(TCP首部)。所以以太网的MSS为1460字节,而Internet的MSS为536字节。
TCP最大负载65535-40B
TCP报文段的最大负载为65495字节,因为每个数据段必须适合IP的载荷能力,不能超过65535字节,IP头20B,TCP包头20B,故最大负载为65535- 20-20=65495B
TCP(传输控制协议) 需要将要传输的文件分段传输,建立会话,可靠传输,流量控制
1.面向连接,只能有两个端点,点到点;提供全双工(同时收和发)既要发了信息,也得收信息确认对方有没有收到
客户端 ===> SYN MSS=1460(最大数据包是1460字节) [seq=0 序列号是0] ===> 服务器
客户端 <=== SYN,ACK [seq=0,ack=1 序列号是0,确认号是1] MSS=1424(服务器最大数据包是1424字节) WS=7(window) win=3737600(服务器最多缓存3737600字节)<=== 服务器
客户端 ===> ACK [seq=1,ack=1 序列号是1,确认号是1] win=66816(客户端最多缓存是66816字节) ===> 服务器
2.面向字节流,比如 发送文件,文件二进制=>TCP发送缓存=>TCP接收缓存=>应用程序,这也是发送和接收窗口技术
3.TCP协议使用滑动窗口技术实现可靠传输
1.停止等待协议效率不高,连续发送确认是窗口技术
2.以字节为单位的滑动窗口技术,连续发送,接收窗口收到后确认,往右滑动发送窗口,接收窗口也要往右滑动
3.如果中间有顺序的包丢了,接收窗口发送确认号的时候,会发丢之前的ack号,选择重发的包序号,选择确认
4.超时重传,tcp每发送一个报文段,就设置一次计时器,重传时间到但还没收到确认,就重传这一报文段,这个时间是加权平均的往返时间
TCP的重发机制是怎么实现的?
1)滑动窗口机制,确立收发的边界,能让发送方知道已经发送了多少(已确认)、尚未确认的字节数、尚待发送的字节数;让接收方知道(已经确认收到的字节数)
2) 超时重传,tcp每发送一个报文段,就设置一次计时器,重传时间到但还没收到确认,就重传这一报文段,这个时间是加权平均的往返时间
3)选择重传,用于对传输出错的序列进行重传,如果中间有顺序的包丢了,接收窗口发送确认号的时候,会发丢之前的ack号,选择重发的包序号,选择确认
TCP报文长度是在TCP三次握手中那一次确定的?
这个是关于TCP报文的最大报文段长度mss的相关问题。在TCP连接的前两次握手中(SYN报文中),通信双方都会在选项字段中告知对方自己期待收到最大报文长度(mss值),以双方两个SYN报文中最小的mss最为本次数据传输的mss值。通信双方以“协商”的方式来确定报文长度的,前两次握手是告诉对方自己的mss值,在第三次握手确定mss值
TCP丢包现象:
TCP Out_of_Order的原因分析:
一般来说是网络拥塞,导致顺序包抵达时间不同,延时太长,或者包丢失,需要重新组合数据单元,因为他们可能是由不同的路径到达你的电脑上面。
TCP Retransmission原因分析:
很明显是上面的超时引发的数据重传。
TCP dup ack XXX#X原因分析:
就是重复应答#前的表示报文到哪个序号丢失,#后面的是表示第几次丢失。
tcp previous segment not captured原因分析
意思就是报文没有捕捉到,出现报文的丢失。
TCP的传输连接管理:
1.连接建立=>数据传输=>连接释放
2.主动发起连接的是客户端,被动接受连接的是服务器
3. 客户端 ==> SYN是1同步 ,ACK确认标志是0,seq序号是x ==> 服务器
客户端 <== SYN是1同步 ,ACK确认标志是1,seq序号是y,ack确认号是x+1 <==服务器
客户端 ==> ACK确认标志是1,seq序号是x+1,ack确认号是y+1 ==>服务器
1.最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
2.TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
3.TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
4.TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
5.TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
4.为什么需要第三次握手再次确认,因为服务器需要确认客户端收到我的回复
5.状态转移
1.客户端发送完变成 SYN-SENT , 服务端接收到后变成SYN-RECEIVED,客户端接收到确认变成 ESTABLISHED,服务端收到确认变成 ESTABLISHED
2.当客户端访问不存在的IP时,可以看到客户端变成SYN-SENT状态,接收不到服务端的确认回复
3.SYN攻击,可以伪造来源ip,因此可以看到服务端变成SYN-RECEIVED状态,接收不到客户端的确认回复
6.四次挥手
客户端(主动关闭) ==> FIN标志是1,seq序号是u ==>服务器
客户端 <== ACK确认标志是1,seq序号是v,ack确认号是u+1 <== 服务器
客户端 <== FIN标志是1,ACK确认标志是1,seq序号是w,ack确认号是u+1 <== 服务器
客户端 ==> ACK确认标志是1,seq序号是u+1,ack确认号是w+1 ==>服务器
7.状态转移
主动关闭的一方是time_wait的状态
被动关闭的一方是close_wait的状态
TCP三次握手中,accept函数是发生在TCP三次握手的那个阶段?
TCP服务端accept发生在三次握手之后
客户端
socket()==>connect()==>write()==>read()
服务端
socket()==>bind()==>listen()==>accept()==>read()==>write()
1.accept过程发生在三次握手之后
2.在调用listen函数之后,一个socket会从主动连接的套接字变为listen 套接字,accept后listen套接字变成连接套接字,listen继续接收更多连接
3.客户端调用connect后,会阻塞,此时是第一次握手
4.服务端调用accept后,会阻塞,等待客户端返回ACK确认,然后会返回,因此是在第三次握手后返回
5.调用accept函数返回是一个连接套接字,它代表着一个网络已经存在的点对点连接
如何保证TCP连接的可靠性
1.数据包校验,发送方计算校验和,接收方结算校验和,进行对比
2.应答机制,seq序列号与ack确认号
3.超时重传机制,发送后启动定时器,进行重传
4.连接管理,三次和四次
5.对失序数据包重排序
6.流量控制和拥塞控制,使用滑动窗口协商大小
TCP在listen时的参数backlog的意义
linux内核中会维护两个队列:
1)未完成队列:接收到一个SYN建立连接请求,处于SYN_RCVD状态
2)已完成队列:已完成TCP三次握手过程,处于ESTABLISHED状态
3)当有一个SYN到来请求建立连接时,就在未完成队列中新建一项。当三次握手过程完成后,就将套接口从未完成队列移动到已完成队列。
4)backlog曾被定义为两个队列的总和的最大值,Berkely实现中的backlog值为上面两队列之和再乘以1.5。
5)如果当客户端SYN到达的时候队列已满,TCP将会忽略后续到达的SYN,但是不会给客户端发送RST信息,因为此时允许客户端重传SYN分节。如果启用syncookies (net.ipv4.tcp_syncookies = 1),新的连接不进入未完成队列,不受影响
6)backlog 即上述已完成队列的大小, 这个设置是个参考值,不是精确值. 内核会做些调整
SYN 洪水攻击(syn flood attack)
通过伪造IP向服务器发送SYN包,塞满服务器的未完成队列,服务器发送SYN+ACK包 没回复,反复SYN+ACK包,使服务器不可用.
启用syncookies 是简单有效的抵御措施.
启用syncookies,仅未完成队列满后才生效.
如果TCP连接过程中,第三次握手失败怎么办?
server端发送了SYN+ACK报文后就会启动一个定时器,等待client返回的ACK报文。如果第三次握手失败的话client给server返回了ACK报文,server并不能收到这个ACK报文。那么server端就会启动超时重传机制,超过规定时间后重新发送SYN+ACK,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries来指定,默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,server自动关闭这个连接。但是client认为这个连接已经建立,如果client端向server写数据,server端将以RST包响应
流量控制和拥塞控制
流量控制:数据的传送与接收过程当中很可能出现收方来不及接收的情况,这时就需要对发方进行控制,以免数据丢失。流量控制用于防止在端口阻塞的情况下丢帧,这种方法是当发送或接收缓冲区开始溢出时通过将阻塞信号发送回源地址实现的。流量控制可以有效的防止由于网络中瞬间的大量数据对网络带来的冲击,保证用户网络高效而稳定的运行。
1.通信双方主机上都分别有一个“发送窗口”和一个“接受窗口”
2.TCP连接阶段,双方协商窗口尺寸
3.发送方根据协商的结果,发送符合窗口尺寸的数据字节流,并等待对方的确认,等待确认机制
4.发送方根据确认信息,改变窗口的尺寸
拥塞控制:网络拥塞现象是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象。拥塞控制是处理网络拥塞现象的一种机制。
1.TCP发送方首先发送一个数据报,然后等待对方的回应
2.得到回应后就把这个窗口的大小加倍,然后连续发送两个数据报
3.直到出现超时错误,这样,发送端就了解到了通信双方的线路承载能力,也就确定了拥塞窗口的大小
关闭连接后为什么客户端最后还要等待2MSL?
MSL(Maximum Segment Lifetime)报文最大生存时间,2MSL即两倍的MSL,TCP允许不同的实现可以设置不同的MSL值。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
1.建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
2.而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
SYN flood攻击:
伪造不存在的地址和目标服务器建立会话
比如102机器向101机器发起建立会话的SYN请求,但是102机器把源IP地址随意编写了一个,101机器会回复确认连接的ACK请求,此时找不到源地址
land攻击:
目标地址和源地址都是目标本身,自己联系自己
三次握手过程中有哪些不安全性
1)伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时,服务器就会存在大量未完成三次握手的连接,服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击
防范措施:
1、降低SYN timeout时间,使得主机尽快释放半连接的占用
2、采用SYN cookie设置,如果短时间内连续收到某个IP的重复SYN请求,则认为受到了该IP的攻击,丢弃来自该IP的后续请求报文
3、在网关处设置过滤,拒绝将一个源IP地址不属于其来源子网的包进行更远的路由
2)当一个主机向服务器发送SYN请求连接,服务器回复ACK和SYN后,攻击者截获ACK和SYN。然后伪装成原始主机继续与服务器进行通信
UDP(用户报文协议) 一个数据包就能完成数据通信,不需要建立会话,不分段,不用流量控制,不可靠传输
用UDP协议通讯时怎样得知目标机是否获得了数据包?
1.可以在每个数据包中插入一个唯一的ID,比如timestamp或者递增的int。
2.发送方在发送数据时将此ID和发送时间记录在本地。
3.接收方在收到数据后将ID再发给发送方作为回应.
4.发送方如果收到回应,则知道接收方已经收到相应的数据包;如果在指定时间内没有收到回应,则数据包可能丢失,需要重复上面的过程重新发送一次,直到确定对方收到。
Tcp流, udp的数据报,之间有什么区别,为什么TCP要叫做数据流?
TCP流和UDP数据报之间的区别
1.TCP本身是面向连接的协议,S和C之间要使用TCP,必须先建立连接,数据就在该连接上流动,可以是双向的,没有边界。所以叫数据流 ,占系统资源多
2.UDP不是面向连接的,不存在建立连接,释放连接,每个数据包都是独立的包,有边界,一般不会合并。
3.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证
UDP使用场景
1.需要资源少,在网络情况比较好的内网,或者对于丢包不敏感的应用。如DHCP协议就是基于UDP的。一般的获取IP地址都是内网请求,而且一次获取不到IP又没事。
2.又比如基于UDP的RTP,TFTP,丢一帧数据问题也不大。再比如一些设备发现协议等等。
3.不需要一对一沟通,建立连接,而是可以广播的应用。DHCP就是一种广播的形式。VXLAN也是需要用到组播,也是基于UDP协议的。
4.需要处理速度快,时延低,可以容忍少数丢包,但是要求即便网络拥塞,也毫不退缩,一往无前的时候。QUIC是Google提出的一种基于UDP改进的通信协议,其目的是降低网络通信的延迟,提供更好的用户互动体验。
SSL:位于传输层和应用层之间,专门实现在传输之前加密,在接收端给应用层之前解密;使用非对称加密技术
SSL原理
1.客户端与服务端建立连接
2.互相Hello(包含支持的版本、算法;加上随机数)
3.服务端发送公钥
客户端发送公钥(双向验证才需要,单向跳过)
服务端验证客户端公钥(双向验证才需要,单向跳过)
4.客户端验证服务端公钥
5.交换DH参数(如果用DH密钥交换算法)
6.客户端使用公钥生成PreMaster Secret,并发送给服务端(DH根据随机数和参数直接算)
7.服务端使用私钥解密PreMaster Secret,得到对称密钥(DH根据随机数和参数直接算)
8.使用对称密钥通讯
SSL客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个ServerHello,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个秘密消息,用SSL服务器的公钥加密后传过去,SSL服务器端用自己的私钥解密后,会话密钥协商成功,双方可以用同一份会话密钥来通信了。
HTTPS工作原理
一.首先HTTP请求服务端生成证书,客户端对证书的有效期、合法性、域名是否与请求的域名一致、证书的公钥(RSA加密)等进行校验;
二.客户端如果校验通过后,就根据证书的公钥的有效, 生成随机数,随机数使用公钥进行加密(RSA加密);
三.消息体产生的后,对它的摘要进行MD5(或者SHA1)算法加密,此时就得到了RSA签名;
四.发送给服务端,此时只有服务端(RSA私钥)能解密。
五.解密得到的随机数,再用AES加密,作为密钥(此时的密钥只有客户端和服务端知道)。
六.秘钥的协商过程是非对称加密,之后的通讯过程是使用此秘钥的对称加密, 非对称加密算法的性能是非常低的,一般的HTTPS连接只在第一次握手时使用非对称加密,通过握手交换对称加密密钥,在之后的通信走对称加密
TLS(传输层安全)是更为安全的升级版 SSL
TLS是升级版的SSL,但是还有按照传统称为了SSL
长连接、短连接的区别和使用
长连接:client 方与 server 方先建立连接,连接建立后不断开,然后再进行报文发送和接收。这种方式下由于通讯连接一直存在。此种方式常用于 P2P 通信。
短连接:Client 方与 server 每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此方式常用于一点对多点通讯。C/S 通信。
长连接与短连接的使用时机:
长连接:短连接多用于操作频繁,点对点的通讯,而且连接数不能太多的情况。每个 TCP 连 接的建立都需要三次握手,每个 TCP 连接的断开要四次握手。如果每次操作都要建立连接然后再操作的话处理速度会降低,所以每次操作下次操作时直接发送数据 就可以了,不用再建立 TCP 连接。例如:数据库的连接用长连接,如果用短连接频繁的通信会造成 socket 错误,频繁的 socket 创建也是对资源的浪 费。
短连接:web 网站的 http 服务一般都用短连接。因为长连接对于服务器来说要耗费一定 的资源。像 web 网站这么频繁的成千上万甚至上亿客户端的连接用短连接更省一些资源。试想如果都用长连接,而且同时用成千上万的用户,每个用户都占有一个 连接的话,可想而知服务器的压力有多大。所以并发量大,但是每个用户又不需频繁操作的情况下需要短连接。
参考 http://www.cnblogs.com/Roberts/archive/2010/12/05/1986550.html
socket 连接步骤
Socket(套接字)概念:套接字(socket)是通信的基石,是支持 TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的 IP 地址,本地进程的协议端口,远地主机的 IP 地址,远地进程的协议端口。
Socket 连接过程
建立 Socket 连接至少需要一对套接字,其中一个运行于客户端,称为 ClientSocket ,另一个运行于服务器端,称为 ServerSocket
套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端
套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
HTTP:
说一下什么是Http协议?
浏览器客户端和服务器端之间数据传输的格式规范,格式简称为“超文本传输协议”。
客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
例如:在浏览器地址栏键入URL,按下回车之后会经历以下流程:
1、浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
2、解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
3、浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
4、服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
5、释放 TCP连接;
6、浏览器将该 html 文本并显示内容;
一次完整的HTTP请求所经历的7个步骤
HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:
1.建立TCP连接
在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建 Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则, 只有低层协议建立之后才能,才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。
2.Web浏览器向Web服务器发送请求行
一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令。例如:GET /sample/hello.jsp HTTP/1.1。
3.Web浏览器发送请求头
浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。
4.Web服务器应答
客户机向服务器发出请求后,服务器会客户机回送应答, HTTP/1.1 200 OK ,应答的第一部分是协议的版本号和应答状态码。
5.Web服务器发送应答头
6.Web服务器向浏览器发送数据
Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。
7.Web服务器关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了响应数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
建立TCP连接->发送请求行->发送请求头->(到达服务器)发送状态行->发送响应头->发送响应数据->断TCP连接
16.什么是代理?
代理是位于客户端和服务器之间的HTTP中间实体。接收所有客户端的HTTP请求,并将这些请求转发给服务器(可能会对请求进行修改之后转发)。
17.什么是缓存?
缓存HTTP的仓库,使常用页面的副本可以保存在离客户端更近的地方。
18.什么是网关?
网关是一种特殊的服务器,作为其他服务器的中间实体使用。通常用于将HTTP流量转换成其他的协议,例如fastcgi。
19.什么是隧道?
隧道是建立起来之后,就会在两条连接之间对原始数据进行盲转发的HTTP应用程序。常见用途是通过HTTP连接承载加密的安全套接字层(SSL)流量,这样SSL流量就可以穿过只允许Web流量通过的防火墙了。
20.什么是Agent代理?
用户Agent代理是代表用户发起HTTP的客户端程序。比如Web浏览器。另外有些自动发送HTTP请求并获取内容的代理,比如“网络蜘蛛”或者“Web机器人”。
HTTP连接管理:
1.HTTP如何使用TCP连接的
2.TCP连接的时延,瓶颈,存在的障碍
3.HTTP的优化,并行连接,keep-alive,管道连接
4.HTTP就是HTTP over TCP over IP,HTTPS是HTTP和TCP之间插入放入TLS或者SSL
5.保持TCP连接的正确运行,四个值<源ip地址,源端口,目的ip,目的端口
6.HTTP时间线,请求=>DNS查询=>响应=>请求=>服务器处理=>响应=>关闭
7.TCP性能点:TCP连接建立握手(花费50%时间);
TCP延迟确认算法(占第二);
TIME_WAIT时延和端口耗尽(记录最近所关闭连接的IP地址和端口号,2MSL通常2分钟)
TCP慢启动拥塞控制;数据聚集的Nagle算法;
HTTP1.1版本新特性
a、默认持久连接节省通信量,只要客户端服务端任意一端没有明确提出断开TCP连接,就一直保持连接,可以发送多次HTTP请求
b、管线化,客户端可以同时发出多个HTTP请求,而不用一个个等待响应
c、断点续传
实际上就是利用HTTP消息头使用分块传输编码,将实体主体分块传输。
HTTP优化方案
TCP复用:TCP连接复用是将多个客户端的HTTP请求复用到一个服务器端TCP连接上,而HTTP复用则是一个客户端的多个HTTP请求通过一个TCP连接进行处理。前者是负载均衡设备的独特功能;而后者是HTTP 1.1协议所支持的新功能,目前被大多数浏览器所支持。
内容缓存:将经常用到的内容进行缓存起来,那么客户端就可以直接在内存中获取相应的数据了。
压缩:将文本数据进行压缩,减少带宽
SSL加速(SSL Acceleration):使用SSL协议对HTTP协议进行加密,在通道内加密并加速
TCP缓冲:通过采用TCP缓冲技术,可以提高服务器端响应时间和处理效率,减少由于通信链路问题给服务器造成的连接负担。
HTTP/2新特性
二进制分帧、多路复用、流优先级、服务器推送、头部压缩、应用层协商协议
*强制SSL,虽然规范没有强制,但是所有浏览器均只支持SSL下的HTTP/2
HTTP/2 Frequently Asked Questions
HTTP首部(head头信息)
1.通用首部:Date
通用缓存首部(Cache-Control)
2.请求首部:Accept
条件请求首部(if-),安全请求首部(Authorization)
3.响应首部:Server
4.实体首部(用于主体部分的首部):content-type:
5.扩展首部:非标准的,自己定义的
HTTP请求报文与响应报文格式
1.请求报文包含四部分:
a、请求行:包含请求方法、URI、HTTP版本信息
b、请求首部字段
c、请求内容实体
d、空行
2.响应报文包含四部分:
a、状态行:包含HTTP版本、状态码、状态码的原因短语
b、响应首部字段
c、响应内容实体
d、空行
3.常见的首部:
通用首部字段(请求报文与响应报文都会使用的首部字段)
Date:创建报文时间
Connection:连接的管理
Cache-Control:缓存的控制
Transfer-Encoding:报文主体的传输编码方式
4.请求首部字段(请求报文会使用的首部字段)
Host:请求资源所在服务器
Accept:可处理的媒体类型
Accept-Charset:可接收的字符集
Accept-Encoding:可接受的内容编码
Accept-Language:可接受的自然语言
Content-Length:表示请求消息正文的长度
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中
Cookie:这是最重要的请求头信息之一
From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它
Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝
Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用
UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型
5.响应首部字段(响应报文会使用的首部字段)
Accept-Ranges:可接受的字节范围
Location:令客户端重新定向到的URI
Server:HTTP服务器的安装信息
6.实体首部字段(请求报文与响应报文的的实体部分使用的首部字段)
Allow:资源可支持的HTTP方法
Content-Type:实体主类的类型
Content-Encoding:实体主体适用的编码方式
Content-Language:实体主体的自然语言
Content-Length:实体主体的的字节数
Content-Range:实体主体的位置范围,一般用于发出部分请求时使用
常见的MIME类型如下:
MIME的编码:
MIME提供了一种可以在邮件中附加多种不同编码文件的方法,弥补了原来的信息格式的不足。实际上不仅仅是邮件编码,现在MIME经成为HTTP协议标准的一个部分。
MIME定义了两种编码方法Base64与QP(Quote-Printable)
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded :