PHP-文件上传
(。・∀・)ノ
学习文件处理本质上面就是学习文件处理的函数。 ヾ(๑╹◡╹)ノ”
世界上最难懂的是道士的鬼符、医生的处方和程序员的正则表达示。(ง •_•)ง
年後の新作2.14(。・∀・)ノ
本文参考PHP中文网:[PHP入门教程之一周学会PHP] [PHP入门视频教程之一周学会PHP]
资料查阅:[W3shcool PHP 教程]
 
 
 
 
 
 
Wireshark是一款世界范围最广、最好用的网络封包分析软件,功能强大,界面友好直观,操作起来非常方便。它的创始人是Gerald Combs,前身是Ethereal,作为开源项目经过众多开发者的完善它已经成为使用量最大的安全工具之一。在CTF中也经常会使用wireshark进行流量数据包分析,可以快速检测网络通讯数据,获取最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。用户将在图形界面中浏览这些数据,实时监控TCP、session等网络动态,轻松完成网络管理工作。
数据包嗅探或协议分析:指捕获和解析网络上传输的数据的过程,以便更好地了解网络上正在发生的事情。
1.应用层:最高的一层,直接面对用户,各种程序都是基于这一层,主要作用是处理传输层提交的信息,与用户交换,并把信息传到下层发送。
2.传输层:主要作用对数据包的分割、重组、连接、管理、排序、重传等等,以及标记逻辑端口号—常见协议:TCP、UDP; 端口0~ 65535个端口,只是应该标识,方便管理(such as:21端口是FTP程序,80端口是HTTP程序,4000端口是QQ)。
3.网络层:主要作用是实现与远程设备的连接,是TCP/IP模型中最重要的一层,封装为 IP头部。封装中的重要部分为IP地址,每台设备唯一。
4.链路层:主要功能在两个网络实体之间提供数据链路链接,最常见的是以太网和IEEE 802封装,封装中有一个重要的部分就是MAC地址(网卡物理地址)。
TCP协议:可靠,面向连接,效验数据,超时重传,有序号,保证数据完整有序到达,但是协议复杂速度稍慢。(适合文件传输和网页浏览,对数据完整有序要求比较高的场合)
**UDP协议:**不可靠,仅发送数据,不保证数据完整有序到达,协议简单速度快。(适合DNS查询,视频聊天,对数据完整有序要求比较低,但对数据即使性要求比较高的场合)
wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡。 点击 Caputre->Interfaces
. 出现下面对话框,选择正确的网卡。然后点击Start
按钮, 开始抓包
WireShark 主要分为这几个界面
 
 
使用过滤是非常重要的, 初学者使用wireshark时,将会得到大量的冗余信息,在几千甚至几万条记录中,以至于很难找到自己需要的部分。搞得晕头转向。
过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。
过滤器有两种:
   一种是显示过滤器,就是主界面上那个,用来在捕获的记录中找到所需要的记录
   一种是捕获过滤器,用来过滤捕获的封包,以免捕获太多的记录。
在Capture->Capture Filters
中设置.
 
保存过滤
在Filter栏上,填好Filter的表达式后,点击 + 按钮,取个名字。比如 “test”。点击OK后Filter栏上就多了个”test” 的按钮。
 
过滤表达式的规则
表达式规则
  1. 协议过滤 比如TCP,只显示TCP协议。
  2. IP 过滤 比如 ip.src ==192.168.1.102显示源地址为192.168.1.102,ip.dst==192.168.1.102, 目标地址为192.168.1.102
  3. 端口过滤 tcp.port ==80, 端口为80的 tcp.srcport == 80, 只显示TCP协议的愿端口为80的。
  4. Http模式过滤 http.request.method==”GET”, 只显示HTTP GET方法的。
  5. 逻辑运算符为 AND/ OR 常用的过滤表达式
1 | 过滤表达式 用途 |
 
 
封包列表的面板中显示,编号,时间戳,源地址,目标地址,协议,长度,以及封包信息。 你可以看到不同的协议用了不同的颜色显示。
你也可以修改这些显示颜色的规则,View->ColoringRules
。
 
 
Packet Details Pane(封包详细信息),这个面板是我们最重要的,用来查看协议中的每一个字段。
各行信息分别为:
Frame: 物理层的数据帧概况
Ethernet II: 数据链路层以太网帧头部信息
Internet Protocol Version 4: 互联网层IP包头部信息
Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP
Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议
TCP包的具体内容
从下图可以看到wireshark捕获到的TCP包中的每个字段。
 
TCP三次握手
看到这, 基本上对wireshak有了初步了解, 现在我们看一个TCP三次握手的实例三次握手过程为:
我们用wireshark实际分析下三次握手的过程。 打开wireshark, 打开浏览器输入 http://www.cr173.com 在wireshark中输入http过滤, 然后选中GET /tankxiao HTTP/1.1的那条记录,右键然后点击”Follow TCP Stream”, 这样做的目的是为了得到与浏览器打开网站相关的数据包,将得到如下图:
图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。
 
第一次握手数据包
客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图
 
第二次握手的数据包
服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的SYN加1以.即0+1=1, 如下
 
第三次握手的数据包
客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图
 
就这样通过了TCP三次握手,建立了连接。 参考文章
 
 
 
 
数组: 相同类型的数据元素按顺序组成的一种线性表,元素在数组中的相对位置由下标来指定。数组中的每个元素通过数组名加下标进行引用。
数组有什么用处?
例:定义100个int型变量,求这100个变量的和。
int x1,x2,x3…x100;
int sum;
sum=x1+x2+…+x100;
这样程序很复杂。
例:定义100个int型变量,求这100个变量的和。
有了数组后,可以这样编程:
int [] x=new int[100];
int sum=0;
for(int i=0;i<100;i++)
{
sum=sum+x[i];
}
这样使得程序编写方便很多。
注意:
Java中,数组是独立的类,有自身的方法,不只是变量的集合。在Java里创建一个数组,需要做如下的工作:
(1)说明一个变量来存放该数组。
(2)建立一个新的数组对象(即创建数组空间)并把它赋给这个数组变量。
(3)在该数组中存储信息。
   ↓↓
例如:String list[ ]=new String[3];
list[0]=“one”;
list[1]=“two”;
 
 
同其他类变量一样,在使用数组前必须先说明它,一维数组说明的格式如下:
  类型 数组名[ ];
或 类型[ ] 数组名;
例如:int list[ ];
int[] list;
String[] args;
String args[];
 
 
创建数组空间必须声明数组的长度,以确定所开辟的内存空间的大小,在Java中实际上就是通过new创建一个新的数组对象并把它赋给这个数组变量。其语法格式如下:
   数组名=new 数组元素类型[数组元素个数]
例如:int[] list; list=new int[3];
数组的说明和构造合并在一起,其语法格式如下:
    类型 数组名[ ]=new 数组元素类型[数组元素个数];]
例如:int list[ ]=new int[3];
 
 
1. 数组的初始化方式有两种:
(1) 像初始化简单类型一样自动初始化数组,即在说明数组的同时进行初始化;
   int a[]={1,2,3,4}
(2) 先定义数组,然后为每个元素赋值。例如:
   int b[]=new int[3];
   b[0]=8;b[1]=9;
 
2. 这样初始化也可以!
另一种形式1:
int[] a=new int[]{1,2,3,4};   等价于: int[] a={1,2,3,4}
{}中的元素个数决定了[]中的元素个数。{}中的元素取值决定了数组a各个元素的取值。
另一种形式2:
int[] a;
a=new int[]{1,2,3,4};
等价于:int[] a=new int[3];
     a[0]=1;a[1]=2;a[2]=3;
     a[3]=4
但是这样定义是错误的:
int[] a;
a={1,2,3,4};
定义数组要注意:
(1) 不能这样定义数组:
     int a[5];
(2)不能这样初始化数组:
     int[] a; a={1,2,3,4};
(3)使用new 创建数组之后,数组中的每个元素被自动初始化为0。
     int [] a=new int[10];
     for(int i=0;i<10;i++)
     { System.out.println(“a[“+i+”]=”+a[i]);
     }
 
 
数组元素的表示方式为:
     数组名[下标]
 
使用数组时要注意:
(1)数组越界异常:Java在对数组元素操作时会对数组下标进行越界检查,以保证安全性。若在Java程序中超出了对数组下标的使用范围则在运行此程序时将出现如下错误信息:
   Exception in thread “main” Java.lang.ArrayIndexOutOfBoundsException
如下的错误即数组越界:int x[]={1,2,3,4};System.out.println(x[4]);
(2)每个数组都有一个属性length来指明其长度,字符串String用length()。
   list.length;
(3)空指针异常
1 | 数组长度lengh的使用 |
 
 
1 | [例3-12] 练习数组的创建和使用 |
 
 
Java中的多维数组实际上是数组的数组。不一定是规则的矩阵数组。
多维数组:数组的数组,例如,二维数组为一个特殊的一维数组,其每个元素又是一个一维数组
 
 
二维数组说明的格式为:
  类型 数组名[ ][ ];
或 类型[ ][ ] 数组名;
例如,说明一个整型的二维数组如下:
  int intArray[ ][ ];或 int[ ][ ] intArray;
 
二维数组的创建:
直接为每一维分配空间,如:
  int a[ ][ ]=new int[2][3];
|||
:-: | :-: | :-:
a[0][0]|a[0][1]|a[0][2]
a[1][0]|a[1][1]|a[1][2]
 
从最高维开始,分别为每一维分配空间,如:
int b[ ][ ]=new int[2][ ];
b[0]=new int[3];
b[1]=new int[5];
b[0][0] | b[0][1] | b[0][2] |
b[1][0] | b[1][1] | b[1][2] |
 
元素的初始化:
(1)直接对每个元素进行赋值。
(2)在说明数组的同时进行初始化。
1 | 例如: int[][] a=new int[3][2]: |
 
总结:与数组操作相关的系统函数
(1)使用Arrays.sort来对数组排序
int x[]=new int[]{3,2,1,4};
java.util.Arrays.sort(x); //对数组x内的元素进行排序(升序)
for(int i=0;i < x.length;i++)
{
System.out.println(x[i]);
}
(2)使用Arrays.binarySearch函数对数组进行二分查找
int [] x=new int[]{2,5,1,6,8,3};
java.util.Arrays.sort(x);
System.out.println(java.util.Arrays.binarySearch(x,1)); //二分查找,在数组x中查找1,输出0 ;如果没找到,则会输出一个<0的数
(3)使用System.arraycopy函数拷贝数组
int [] x;
x=new int[]{3,1,2,4};
int [] y;
y=new int[4];
System.arraycopy(x,0,y,0,4);
//将数组x内的 4个元素拷贝给数组y
(4)使用Ayyars.fill函数填充数组
int [] x;
x=new int[]{3,1,2,4};
java.util.Arrays.fill(x,7); //数组x中的4个元素都改为7
 
 
 
 
 
 
 
 
变量定义语句用来定义一个变量,基本格式为:
   类型 变量名1, 变量名2…;
例:char c=‘a’; int i,j=1;
赋值语句是将表达式的值赋给变量,其格式为:
  变量=表达式;
例: char c; c=‘a’;
方法调用语句的一般形式为:
  对象.方法名( 实参数列表 );
例如 System.out.println(“Example!”);
方法调用语句的一般形式为:
  ;//这是一条空语句
输入和输出是Java程序的重要组成部分,它提供了人机交互的手段,它们属于方法调用语句。具体使用方法参考本博客IO使用方法。
1. 输入输出
输入是指把需要加工的数据放到程序中,read
输出则把程序处理的结果呈现给用户,write
2. 标准输入输出
一般用键盘作为标准的输入设备
显示器则是标准的输出设备
通过System.in和System.out对象分别与键盘和显示器发生联系进行输入和输出。
 
📒1. 标准输出System.out对象
System.out对象中包含的最常用的方法是:
println(参数) 向标准输出设备(显示器)打印一行文本并换行
print(参数) 向标准输出设备(显示器)打印一行文本但不换行
参数类型:boolean , char char[] ,double ,float ,int ,
long , Object,String
例如:System.out.println(“Example”);
System.out.print(“Input Name”);
int x=2; System.out.print(x);
 
📒2. 标准输入System.in对象
System.in是字节流,作用是从标准输入读一个字节,常用的方法如下:
int read()  从流中读取一个字节并将该字节作为整数返回,若没有数据则返回-1
int read(byte b[])  从流中读取多个字节放到b中, 返回实际读取到的字节数
int read(byte b[],int off,int len)  从流中读取最多len字节的数据, 放到数组b的下标off开始的单元中,返回读取到的字节数
1 | [例3-1] ReadChar.java 从键盘读一个字符 |
思考:如何接收用户向程序输入的参数?
通过System.in
通过main(String[] args)中的形参
class test{
public static void main(String[] args){
System.out.println(args[0]);
System.out.println(args[1]);
}
}
java test s1 s2
s1
s2
 
📒if-else语句的语法形式:
if (布尔表达式)
{ 语句块1 }
[ else
{ 语句块2 } ]
若语句块1,语句块2也是if-else语句便形成嵌套
1 | 例[3-4]:三个整数a,b,c,要求按从小到大的次序输出 |
**📒 if–else 语句的嵌套** if-else语句中内嵌的语句1或语句2又是if-else语句的情况称为if-else语句的嵌套。如: if(布尔表达式1) 语句1 else if(布尔表达式2) 语句2 … else if (布尔表达式m) 语句m else 语句n |
1 | [例3-5] 求一元二次方程(aX2+bX+c=0)的根: |
1 | 课堂练习:求最小数 |
 
switch语句根据表达式的结果来执行多个可能操作中的一个,它的语法形式如下:
1 | switch(表达式) |
 
注意: “case 常量”只起语句标号的作用,并非在该处进行条件判断。在执行switch语句时,根据switch括号中表达式的值找到匹配的入口标号,就从此标号所标记的语句开始执行下去,不再进行判断,直到遇到break语句为止。
1 | 演示有break及没有break的情况 |
 
使用switch-case必须注意:
1. 表达式必须是符合byte,char,short和int类型的表达式,不能是浮点类型或字符串,case子句中常量的类型必须与表达式的类型相容,且每个常量必须不同;
2. case后面可以有多条语句,不用加{};
3. default子句是可选的。如果有default,当表达式的值与case子句的值都不匹配时就会执行default分支,如果既没匹配也没default,那就什么也不执行;
4. break为跳转语句,表示跳出switch结构,即终止switch语句的执行。如果没有break语句,则switch在执行完一个case分支后,流程控制转移到下一个case继续执行,不再匹配,直到遇到break为止。
5. 多个case子句可以共享相同的语句块;
6. 通过if-else语句可以实现switch语句所有的功能。但通常使用switch语句更简练,且可读性强,程序的执行效率也高;
7. if-else语句可以基于一个范围内的值或一个条件来进行不同的操作,但switch语句中的每个case子句都必须对应一个单值。
1 | [例3-6] 用switch语句判断一个月份属于一年哪个季节(春、夏、秋、冬)。 |
 
 
while语句形式如下:
   while (布尔表达式) {语句块}
说明:while:语句的关键字; 布尔表达式:循环条件; 语句块:循环体,是一个语句,若是多个语句则应构成复合语句。
1 | [例3-7] Sum1.java用while循环语句计算s=1+1/2+1/3+…+1/100 |
 
 
do-while语句的语法形式如下:
   do{
   语句块
   }while(布尔表达式);
说明:do:语句的关键字; 语句块:循环体,是一个语句,若是多个语句则应构成复合语句; 布尔表达式:循环条件。
1 | [例3-8] Sum2.java 用do-while循环语句计算s=1+2+3+……100 |
 
 
for语句的语法形式为:
  for(表达式1;表达式2;表达式3)
   { 语句块
   }
说明:(表达式1;表达式2;表达式3):循环条件; 语句块:循环体,是一个语句,若是多个语句则应构成复合语句。
for语句的执行过程如下:
(1)按表达式1将初值赋给循环控制变量;
(2)按表达式2判断循环是否成立,如果成立则执行循环体,否则退出循环;
(3)执行一次循环后,执行表达式3修改控制变量。
1 | [例3-9] sum3.java 编程求S=12+22+…92 |
**for语句使用注意:**
1. 逗号语句分隔的语句系列,被看作一个语句,这样就可以在只能放一个语句的地方放任意多个语句,只须用逗
号将它们分隔开。如:
for ( i=1,j=10;i < j;i++,j--)
{ …… }
2. 表达式1、表达式2及表达式3都可以为空语句(但分号不能省略) 如:
for( ; ; ) { … } 相当于while(true)
循环的嵌套: |
1 | [例3-10] 百鸡问题。 |
 
 
作用: 使程序的流程从一个语句块的内部跳转出来。
(1) 从switch语句的分支中跳出来
(2) 从循环体内跳出来
对上述的(1)(2)举例如下:(1) break用于跳出switch语句
1 | switch(grade) |
1 | 习题1:分析该程序的输出结果 |
 
(2) break用于跳出循环体
break可用于跳出for循环、while循环、do while循环。
1 | int sum=0; |
 
 
如果break在多重循环中,只退出break所在的那层循环到外层循环中。
1 | int sum=0; |
 
 
作用:用来结束所在循环语句块的本次循环
注意:continue语句只能在循环语句中使用。
1 | [例3-11] ConDemo.java |
 
 
循环体中使用break语句和continue语句的区别:
Break语句 结束整个循环,不再判断执行循环的条件;
Continue语句只结束本次循环,而不是终止整个循环的执行。
 
 
格式: return 表达式;
用途:
(1) 结束方法的运行,并返回一个值;
(2) 如果该方法没有返回值(void),则return后不能跟表达式。
例如: return 0;
    return;
思考:分析以下程序运行结果
1 | 1. |
 
 
 
 
 
 
 
 
 Java可以对各种类型的数据进行加工,这种加工过程称为运算 。其中表示各种不同运算的符号称为运算符 ,参与运算的数据称为操作数 。操作数和运算符按一定语法形式组成的符号序列称为表达式。每个表达式经过运算后都会产生一个确定的值。
**📒运算符按其功能分为七类:**
1. 算术运算符 + 、-、 \*、 /、%、 ++、 --
2. 关系运算符 > 、<、 >=、 <=、 ==、 !=
3. 逻辑运算符 !、&&、||、&、|
4. 位运算符 >>、<<、>>>、&、|、^、~
5. 条件运算符 ?:
6. 赋值运算符 =、+=、-= 、\*= 、/=
7. 其他:下标运算符[]
📒运算符按其要求的操作数个数分为三种:
|
 
**📒算术运算符中的单目运算符**
如 +(一元加,取正值)、
-(一元减,取负值)、
++ (增1运算符)、\-\- (减1运算符)
增1运算符(++)和减1运算符(--): (1)增1运算符(减1运算符)在操作数的前面,首先对操作数本身进行增减1运算,然后再参与其所在表达式的 |
1 | 练习题1:写出该程序的输出结果 |
**📒算术运算符中的双目运算符 **
如 +(加)、-(减)、\*(乘)、/(除)、 % (取余数或取模)。
+,-,\* 是通常意义的加、减、乘
如果整数相除,则结果取整。如 5/2 得到结果2。
如果浮点数相除,则是我们通常意义上的除法,如5.0/2.0结果为2.5。
%是取余,如 5%2结果为1
5.2%2结果为1.2
5.2%2.2结果为0.8
10%-4结果2; -10%-4结果-2
注意: 如果整数相除或取模 第二个操作数为0 编译无错 运行会出错 抛出异常;
|
思考:某个培训中心要为新到的学员安排房间,假设共有x个学员,每个房间可以住6人,让你用一个公式来计算他们要住的房间数?
答案: (x+5)/6
这也可以用于计算留言板的页数。
 
 
1 | class test |
 
📒关系表达式
 
 
1 | 例:分析下列程序的输出结果 |
 
 
1 | 例:分析下列程序的输出结果 |
注意:
(1)右移n位后的结果与除以2的n次方效果相同
(2)左移n位后的结果与乘以2的n次方效果相同
(3)无符号右移要慎重
思考: 如何用一个表达式计算2的X次方?
答案: 1<<x
将1左移x位
 
 
**(1)简单赋值运算符 = **
将等号右边的表达式的值赋给等号左边的变量
例如: int c,d;
c=1;
d=c+10;
**(2)复合赋值运算符 +=、-=、*=、/=、%= 等**
一般形式为: 变量 op= 表达式
等价于: 变量 =变量 op 表达式
c += a; //c = c +a;
c -= a; //c = c -a;
c *= a; //c = c * a;
例:int a=1; 注意:
|
 
 
Java 中唯一的三元运算符,其格式如下:
  变量 = <布尔表达式> ? <表达式1> : <表达式2>
含义是:当<布尔表达式>为真时,变量的值为<表达式1>的值,否则为<表达式2>的值。
1 | 例: 条件运算 |
 
 
表达式的运算次序取决于表达式中各种运算符的优先级。
(1)优先级高的先运算,优先级低的后运算。
(2)括号( )的优先级最高。
(3)优先级相同的情况下要考虑结合性,即从左向右运算还是从右向左运算。
Java语言规定的运算符的优先级如下表所示
**运算符的优先级与结合性的一些规律:**
1. 优先级
() > 单目运算符 > 双目运算符 > 三目运算符 > 赋值运算符
双目: 算术>关系>逻辑 。
2. 结合性
大多数运算符结合性为从左至右
赋值运算符的结合性为从右至左
int a,b=3,c=5;
a = b = c; //结果:a、b、c均为 5
表达式写法的习惯: (1) 除非是简单的直观运算,应该尽量使用括号 |
1 | 例: |
 
表达式写法的习惯:
(1) 除非是简单的直观运算,应该尽量使用括号
(2)另外,尽量不要写太长的表达式,过长的表达式容易引 起对求值次序的误解。
 
 
(1) Java中整型、实型、字符型数据可以混合运算。
运算过程中,Java自动把精度较低的类型转换为另一种精度较高的类型。
(2) 低精度的值赋给高精度的变量可以自动转换,不出现编译错误;相反会出现编译错误,需要强制转换。
例如: float x=(float)5.0;long x=2;
注意: 如果byte、short、char在一起运算时,会先将这些值转换为int型。再进行运算,结果为int型。 如表达式中一个变量是int型,另一个是long型,则先将int型转为long型,再进行计算。最后结果为long型。
1 | 下列代码会编译出错,提示c = (a + b);有精度损失 |
练习题3:
下列表达式结果是什么类型?
‘A’+2+2.5
double
 
 
在Java中直接将高精度的值赋给低精度的变量会导致编译出错。这时可用强制类型转换来解决。
形式为:
   (类型名)表达式
例如:
int i; byte b,c;
b=(byte)345; //上机测试知b得到89
c=(byte)356; //上机测试知c得到100
i=(int)(3.8+6); //强制转换后小数部分被截去,i得到9,不会四舍五入
注意:
1 | 加上强制类型转换,下列代码编译通过。 |
**运算时注意(一般的运算都有类型提升功能):** (1)在运算过程中,运算的结果至少是int型,即如果参与运算的两个数级别比int型低或是int型,则结果为 int型; (2)参与运算的数据如果有一个级别比int型高,则运算结果的类型与类型级别高的数相同; (3)参与运算的两个数据如果类型不一样,会先把低级的数据转换成高级的类型的数据后再作运算,结果是高 级的类型。 |
 
 
Java中允许把int类型的常量赋给byte、short变量时不需要强制类型转换
byte b=123;//合法
short s=123;//合法
b=b+3; //不合法
 
但是把int类型的变量赋给byte、short类型的变量时必须强制转换,否则会出错
int i=123;
byte b=i; //正确的做法是byte b=(byte)i;
byte a = 1; byte c = (byte)(a + b);
练习
设x,y,a分别为float,double,byte型变量,x=3.3,y=2.9,a=5, 则表达式x+ (int)y/ 3*a的值为多少?值的类型是什么?