CP与UDP不同,它是基于连接的,也就是说:为了在服务端和客户端之间传送TCP数据,必须先建立一个虚拟电路,也就是TCP连接。
问题就出在TCP连接的三次握手中,假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大,最后的结果往往是堆栈溢出崩溃—即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从正常客户的角度看来,服务器失去响应,这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。
rst是复位报文 几种TCP链接中出现rst的情况 1.端口未打开 2,请求超时 3,提前关闭 4,在一个已关闭的socket上出现数据
前28位为网络号,故子网掩码为11111111.11111111. 11111111. 11110000(255.255.255.240)。
256-240=16,有16个子网,每一个子网段大小范围是16。
10.11.12.91/28中91可以表示为:01011011,前四位为网络号,后四位为主机号,
故包含10.11.12.91的子网范围是:0101000001011111(8095)。
去掉第一个和最后一个,和 10.11.12.91/28在一个网段的范围为: 10.11.12.81/28~ 10.11.12.94/28。
当通过网络发送该数据时,x86系列 CPU都是Little-Endian的,所以int 型变量值为 0x78563412, 网络发送数据时,采用Big-Endian,先发送高位再发送低位。相当于cpu先反过来排,网络再顺着发。
补:
小端法(Little-Endian)就是低位字节排放在内存的低地址端(即该值的起始地址),高位字节排放在内存的高地址端;
大端法(Big-Endian)就是高位字节排放在内存的低地址端(即该值的起始地址),低位字节排放在内存的高地址端;
解析:子网掩码写成二进制形式则为:1111 1111 1111 1111 1111 1111 1111 11110 0000 0000;可用地址为2^9=512;但是要减去全0和全1,并且要减去一个网关设备,所以512-3=509.
1、因为ping的话 后面跟的是地址,所以要先将域名转换为ip地址,即用到了DNS
2、获取到ip地址后,在数据链路层是根据MAC地址传输的,所以要用到ARP解析服务,获取到MAC地址
3、ping功能是测试另一台主机是否可达,程序发送一份ICMP回显请求给目标主机,并等待返回ICMP回显应答,(ICMP主要是用于ip主机、路由器之间传递控制信息,控制信息是指网络通不通,主机是否可达)
4、TCP的话,不涉及数据传输,不会用到
C类地址默认掩码为255.255.255.0
6个公司二进制为110, 有3位
所以在第4段中前3位置1,11100000->224
所以D
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
public class FrogMaze {
static int n = 0;
static int m = 0;
// 当前求解方案走完剩余的能量
static int maxResidueEnergy = 0;
// 迷宫地图
static int[][] map;
// 是否能出去
static boolean canSolve = false;
// 路径
static String path = "";
// 保存当前走过的点
static LinkedList<String> linkedList = new LinkedList<>();
public static void main(String[] args) {
// 输入操作
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
n = scanner.nextInt();
m = scanner.nextInt();
int p = scanner.nextInt();
map = new int[n][m];
// 迷宫地图录入
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = scanner.nextInt();
}
}
runMap(0, 0, P);
if (!flag)
System.out.println("Can not escape!");
else
System.out.println(path)
}
public static void enterMaze(int x, int y, int energy) {
// 递归越界,能量耗完,当前点不能走
if (energy<0 || x<0 || y<0 || x>=n || y>=m || map[x][y]==0) {
return;
} else {
// "-"作为分隔符,方便更新路线操作
linkedList.push("["+x+","+y+"]-");
// 将当前块记0,使之后的点不能再走
map[x][y] = 0;
// 当前找到了出口
if (x==0 && y==m-1) {
// 本次方案剩余的能量值比当前花费最少的方案剩余的能量还多,进行最优路径的更新
if (energy >= maxResidueEnergy) {
maxResidueEnergy = energy;
updatePath();
}
map[x][y] = 1;
canSolve = true;
return;
}
// 向上
enterMaze(x-1, y, energy-3);
// 向右
enterMaze(x, y+1, energy-1);
// 向下
enterMaze(x+1, y, energy);
// 向左
enterMaze(x, y-1, energy-1);
map[x][y] = 1;
linkedList.removeLast();
}
}
/**
*
*/
public static void updatePath() {
StringBuilder sb = new StringBuilder();
Iterator<String> iterator = linkedList.iterator();
while (iterator.hasNext()) {
sb.append(iterator.next());
}
path = null;
// 以 - 作为分隔符切分
String[] paths = sb.toString().split("-");
sb.delete(0, sb.length());
for (int i = paths.length-1; i >= 0; i--) {
sb.append(paths[i]).append(",");
}
// 删除最后一个","
if (sb.length() > 0) {
sb.deleteCharAt(sb.length()-1);
}
path = sb.toString();
}
}