网站后台案例

一、框架标签(frameset)

frameset(使用时代替了body,因此需要删除body标签)

  1.frame: 加src属性添加其他h5文件
  2.cols/rows:确定是行/列占比

在使用前需要写出aaa/bbb/ccc三个h5文件

此为aaa.html文件内容(只含body内代码):

1
2
3
<body bgcolor="#1859A5">
123
</body>

此为bbb.html文件内容(只含body内代码):

1
2
3
4
5
<body bgcolor="red">
<a href="data.html" target="rigthFrame">收件箱 //意思就是收件箱连接着data.html然后结果输出到名字为rigthFrame的地址
<a href="#">发送箱
<a href="#">已读
</body>

此为ccc.html文件内容(只含body内代码)::

1
2
3
<body bgcolor="yellow">
789
</body>

此为data.html文件内容(只含body内代码):

1
2
3
<body>
这里面要放置后面的数据
</body>

此为模拟qq邮箱界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	<!--frameset 框架标签
1.frame: 加src属性添加其他h5文件
2.cols/rows:确定是行/列占比
-->

<frameset rows="15%,*,"> //将框架分为上下两行
<frame src="aaa.html">

<frameset cols="15%,*"> //将第一次分的下面分为两列
<frame src="bbb.html">
<frame src="ccc.html" name="rigthFrame"> //将ccc.html命名为rigthFrame 方便其他链接找到

</frameset>


</html>

主页界面

选择收件箱之后-输出的东西输出到ccc.html的区域:


网站注册案例

一、举例学习注册页面所需的标签(只展示body内部代码)

form表单标签 最终将整个表单提交

  1.action:提交的地址(之后跳转的地方)
  2.method:
    get:(默认提交方式) 参数拼接在链接之后 有大小限制(4k)
    post: 参数封装在请求体中 没有大小限制

input输入框标签 选择各种样式输入选择

  1.type:指定输入样式(单选/多选/输入)
    text : 文本
    password : 密码框
    radio : 单选按钮(可以使用name=”sex” 放入同一个类 从而单选)
    checkbox : 复选框
    file : 上传文件
    img:图片
    submit : 提交按钮
    button : 普通按钮
    reset : 重置按钮
    hidden : 隐藏域
    date(datetime/datetime-local) : 日期类型
    tel : 手机号
    number : 只允许输入数字

  2.name:(表单提交时)参数名称
  3.id:输入项取一个名字(后期好找)
  4.placeholder:再输入前放置一个提示句

textarea文本域 : 输入一段文字

  1.cols : 指定宽度
  2.rows : 指定的是高度

select下拉选择: 下拉可以选择(籍贯)

  1.option:写有关信息


具体实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

<!--表单标签 form
1.action:提交的地址(之后跳转的地方)
2.method:
get:(默认提交方式) 参数拼接在链接之后 有大小限制(4k)
post: 参数封装在请求体中 没有大小限制
-->


<!-- input
1.type:指定输入样式(单选/多选/输入)
2.name:(表单提交时)参数名称
3.id:输入项取一个名字(后期好找)
4placeholder:再输入前放置一个提示句
-->

<!-- textarea(文本框)
cols:行
rows:列
-->
<!-- select(选择)
option
-->

<form action="../04-网页首页/网站首页.html" method="get">
<input TYPE="hidden" value="asdasdasdasd">
用户名:<input type="text" placeholder="请输入用户名"/><br>
密码:<input type="password"/><br>
确认密码:<input type="password"/><br>
邮箱: <input type="text" /> <br >
手机号码: <input type="tel" /> <br >
照片:<input type="file"/><br>
性别:<input type="radio" name="sex"/>男<input type="radio" name="sex"/>女<br>
爱好:<input type="checkbox">抽烟
<input type="checkbox">喝酒
<input type="checkbox">烫头
<input type="checkbox">写代码<br>
择偶要求:<textarea cols="40" rows="4"></textarea><br>
籍贯:<select>
<option>--请选择--</option>
<option>西安</option>
<option>武汉</option>
<option>北京</option>
</select><br>
验证码:<input type="text"><br>
出生日期:<input type="date"><br>
<input type="submit" value="注册">
<input type="button" value="普通按钮">
<input type="reset" value="重置按钮"><br>
</form>

结果展示:


二、网站注册分析
创建一个5行一列的表格
1. logo部分 一行三列的表格放两个图片和三个假的#便签
2. 导航栏 五个假的#标签
3. 注册部分 分为10*2的表格然后使用到表格合并 添加一些input标签和图片文字
4. 页脚图片 加图片
5. 网站声明信息 七八个假的#标签

分析界面:


三、具体实现代码(只写body部分代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<table border="" width="100%">
<!-- 1. logo部分-->
<tr>
<td>
<table border="" width="100%">
<tr>
<td><img src="../img/logo2.png"></td>
<td><img src="../img/header.png"></td>
<td>
<a href="#">登录</a>
<a href="#">注册</a>
<a href="#">购物车</a>
</td>
</tr>
</table>
</td>
</tr>

<!--2. 导航栏-->
<tr bgcolor="black">
<td>
<a href="#"><font color="white">首页</font></a>
<a href="#"><font color="white">手机数码</font></a>
<a href="#"><font color="white">电脑办公</font></a>
<a href="#"><font color="white">手提箱包</font></a>
<a href="#"><font color="white">家电</font></a>
</td>
</tr>

<!--3. 注册部分-->
<tr >
<td background="../image/regist_bg.jpg" height="1000px"> <!--增加一个背景-->

<table border="5px" width="60%" height="80%" bgcolor="white" align="center">
<tr>
<td>
<form action="注册入门案例.html">
<table width="60%" height="80%" align="center">
<tr>
<td colspan="2"><font color="blue" size="8">会员注册</font> USER REGISTER</td>
</tr>
<tr size="6">
<td size="6">用户名:</td>
<td>
<input type="text" placeholder="请输入用户名"/>
</td>
</tr>
<tr>
<td>密 码:</td>
<td>
<input type="password" placeholder="请输入密码"/>
</td>
</tr>
<tr>
<td>确认密码:</td>
<td>
<input type="password" placeholder="请再次输入密码"/>
</td>
</tr>
<tr>
<td>email:</td>
<td>
<input type="text" placeholder="请输入邮箱"/>
</td>
</tr>
<tr>
<td>姓名:</td>
<td>
<input type="text" placeholder="请输入真实姓名"/>
</td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="sex" /> 男
<input type="radio" name="sex" /> 女
<input type="radio" name="sex" /> 妖
</td>
</tr>
<tr>
<td>出生日期:</td>
<td>
<input type="date" />
</td>
</tr>
<tr>
<td>验证码:</td>
<td>
<input type="text" />
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="注册" />
</td>
</tr>
</table>
</form>

</td>
</tr>
</table>



</td>
</tr>

<!--4. 页脚图片-->
<tr>
<td>
<img src="../image/footer.jpg" width="100%" />
</td>
</tr>

<!--5. 网站声明信息-->
<tr>
<td align="center">
<a href="#">关于我们</a>
<a href="#">联系我们</a>
<a href="#">招贤纳士</a>
<a href="#">法律声明</a>
<a href="#">友情链接</a>
<a href="#">支付方式</a>
<a href="#">配送方式</a>
<a href="#">服务声明</a>
<a href="#">广告声明</a>
<br />
Copyright © 2005-2016 购物商城 版权所有
</td>
</tr>

</table>
</body>
</html>

实现页面如下:


HTML网站首页案例

一、分析设计
  将首页分为一个8*1的表格

1.第一部分:LOGO部分嵌套一个1*3的表格

2.第二部分:导航栏部分 放置5个超链接

3.第三部分:轮播图 放置图片

4.第四部分: 展示产品嵌套一个3*7的表格

5.第五部分:广告位置放置图片

6.第六部分:展示产品嵌套一个3*7的表格

7.第七部分:广告位置放置图片

8.第八部分:最低端放置超链接

分析图


二、详细设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在线购物网址</title>
</head>
<body>
<table border="1px" width="100%"> <!--让表格显示边框之后宽度为100%填充全部-->

<!--第1行 嵌套一个1*3的表格-->
<tr bgcolor="mintcream"> <!--给第1部分给个背景色-->
<td>
<table border="1px" width="100%">
<tr>
<td><img src="../img/logo2.png" ></td> <!--加图片-->
<td><img src="../img/header.png" ></td> <!--加图片-->
<td>
<a href="#" >登录</a> <!--#当做假链接 -->
<a href="#" >注册</a>
<a href="#" >购物车</a>
</td>
</tr>
</table>
</td>
</tr>

<!--第2行 放置5个超链接-->
<tr bgcolor="black"> <!--背景色设置为黑色-->
<td hegith="50px"> <!--给个高度-->
<a href="#" ><font color="white">首页</font></a> <!--#当做假链接 给字体设定白色-->
<a href="#" ><font color="white">手机数码</font></a>
<a href="#" ><font color="white">鞋靴箱包</font></a>
<a href="#" ><font color="white">电脑办公</font></a>
<a href="#" ><font color="white">香烟酒水</font></a>
</td>
</tr>

<!--第3行 放置图片-->
<tr>
<td><img src="../img/1.jpg" width="100%"></td> <!--第3行 放置图片然后设置宽度为100%填充好->
</tr>


<!--第4行 嵌套一个3*7的表格-->
<tr>
<td>
<table border="" width="100%" height="500px"> <!--让表格显示边框之后宽度为100%填充全部-->
<tr>
<td colspan="7">
<h3>最新商品<img src=../img/title2.jpg></h3>
</td>
</tr>

<tr align="center">
<td rowspan="2" width="206px" height="480px"> <!--左边大图-->
<img src="../products/hao/big01.jpg">
</td>

<td colspan="3" heigth="240px" > <!--中间大图-->
<img src="../products/hao/middle01.jpg" width="100%" hegith="100%">
</td>

<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
</tr>

<tr align="center">

<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
</tr>
</table>
</td>
</tr>

<!--第5行 放置图片-->
<tr>
<td>
<img src="../products/hao/ad.jpg" width="100%" />
</td>
</tr>

<!--第6行 嵌套一个3*7的表格-->
<tr>
<td>
<table border="" width="100%" height="500px"> <!--让表格显示边框之后宽度为100%填充全部-->
<tr>
<td colspan="7">
<h3>最新商品<img src=../img/title2.jpg></h3>
</td>
</tr>

<tr align="center">
<td rowspan="2" width="206px" height="480px"> <!--左边大图-->
<img src="../products/hao/big01.jpg">
</td>

<td colspan="3" heigth="240px" > <!--中间大图-->
<img src="../products/hao/middle01.jpg" width="100%" hegith="100%">
</td>

<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
</tr>

<tr align="center">
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
<td>
<img src="../products/hao/small06.jpg" />
<p>洗衣机</p>
<p><font color="red">$998</font></p>
</td>
</tr>
</table>
</td>
</tr>

<!--第7行 放置图片-->
<tr>
<td>
<img src="../image/footer.jpg" width="100%" />
</td>
</tr>

<!--第8行 放置超链接-->
<tr>
<td align="center">
<a href="#">关于我们</a>
<a href="#">联系我们</a>
<a href="#">招贤纳士</a>
<a href="#">法律声明</a>
<a href="#">友情链接</a>
<a href="#">支付方式</a>
<a href="#">配送方式</a>
<a href="#">服务声明</a>
<a href="#">广告声明</a>
<br/>
Copyright © 2005-2016 购物商城 版权所有
</td>
</tr>

</table>
</body>
</html>

最终样式展示:


HTML

一、超文本标记语言

  1. HTML:Hyper Text Markup Language 超文本标记语言
  2. 标记语言:通过一组标签<关键字>

二、HTML语法规范

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
//头部head---浏览器的名字
<head>
<meta charset="utf-8">//默认字体
<title>H5的练习</title>
</head>
//内部body---浏览器内显示内容
<body>
<p>床前明月光</p>//p为其中一个
<p>疑是地上霜</p>
<p>举头望明月</p>
<p>低头思故乡</p>
</body>
</html>

三、各种标签学习(只展示body内部代码)

总结:

  • 段落基础标签

    hr      水平线

br      换行
p      分段(成对出现)
h1-h6
   分级标签(成对出现)
font     变颜色(成对出现)
b/strong(有语气)  加粗(成对出现)
i/em        斜体(成对出现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	<h3>寒假社会实践</h3>

<!--水平线hr-->
<hr>

<!--分段p-->
<P>为更好地推动青年志愿服务参与乡村振兴,按照中央文明办<font color="red">“圆梦工程”</font>——农村未成年人思想道德建设志愿服务行动总体部署,团中央青年志愿者行动指导中心、中国青年志愿者协会拟继续支持基层团组织实施“助力乡村学校少年宫建设”志愿服务项目。</P>

<!--加粗b/strong(加语气) 斜体i/em-->
<P><b><i>“助力乡村学校少年宫建设”</i></b>志愿服务项目是“关爱行动”和“圆梦工程”的子项目,由团中央青年志愿者行动指导中心、中国青年志愿者协会共同组织实施。主要内容是组织、动员基层志愿服务组织,与文体师资力量不够的“乡村学校少年宫”所在农村学校建立长期结对关系,围绕课外活动、素质拓展、安全自护、思想引导、心理辅导等内容,定期选派青年志愿者配合学校开展志愿服务活动,助力“乡村学校少年宫”建设。</P>

<P>拟从中西部18个省(自治区、直辖市)、新疆生产建设兵团中遴选、支持50个左右的贫困地区县级团委或地市级、县级青年志愿者协会,共覆盖250所学校示范实施“助力乡村学校少年宫建设”志愿服务项目。</P>

<P>相关省级团委青年志愿者工作机构要高度重视,精心组织,结合辖区内现有乡村学校少年宫分布和当地志愿服务团队等情况,做好相关申报工作,遴选、指导申报地填写《2019-2020年度“助力乡村学校少年宫建设”志愿服务项目基层团组织申报表》(附件1),于2020年2月10日前将经审核的申报表统一发送至工作邮箱zyzgzb_2@163.com。</P>

代码结果如下:


  • 网站图片标签

img src 指定图片路径

  1.width 宽度
  2.heigth 高度
  3.alt 文件加载失败时的提示信息

`<img src="../img/10.jpg"  width="200px"  heigth="200px" alt="这张图片可能加载有问题"/>`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<!--
常用属性:
src:指定图片路径
width:宽度
heigth:高度
alt:文件加载失败时候的提示信息
-->

<!--
路径寻找问题:
./ 当前路径
../ 上一级路径
../../ 上上一级路径
-->
<img src="../img/10.jpg" width="200px" alt="这张图片可能加载有问题"/>

  • 链接标签

    ul  无序列表

  1.li 一行
  2.type 是哪种小图标disc(实心圆)/square(正方形)/circle(空心圆)

ol  有序列表

  1.type(属性) —1/a/i/I
  2.start(属性) —哪类型从哪个开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

<!--无序列表 ul
1. li(标签) ---列
2. type(属性) --- disc(实心圆)/square(正方形)/circle(空心圆)
-->
<ul type="square">
<!--一列 li -->
<li>百度</li>
<li>新浪微博</li>
<li>黑马程序员</li>
</ul>

<hr><!--下划线-->

<!--有序列表 ol
1.type(属性) ---1/a/i/I
2.start(属性) ---哪类型从哪个开始
                     -->
<ol type="1" start="2">
<!--一列 li -->
<li>百度</li>
<li>新浪微博</li>
<li>黑马程序员</li>
</ol>

代码结果如下:

href 超链接标签a

 1.href:指定跳转的链接地址  http协议(别人的)/文件路径(自己的)
 2.target:用什么形式打开     当前窗口(_self)/新建窗口(_blank)

1
2
3
4
5
6
7
8
9
10
11
12
13
14

<!--无序列表-->
<ul type="circle">
<!--
超链接标签 a
1.href(属性):指定要跳转去的链接地址 需要加上http协议(别人的)/文件路径(自己的)
2.target:用什么形式打开
2.1: _self 当前窗口(默认)
2.2: _blank 新开一个窗口
-->
<li><a href="https://www.baidu.com/" target="_blank">百度</li>
<li><a href="https://www.bilibili.com/">哔哩哔哩</li>
<li><a href="http://dasai.lanqiao.cn/">蓝桥杯</li>
</ul>

  • 表格标签

    table 生成表格

tr
td

  1.border:边框(表格有边框)
  2.width:宽度
  3.height:高度
  4.bgcolor:背景色(tr td也可以用)
  5.align:对齐方式(tr td也可以用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

<!--
表格:table
常用属性:
1.border:边框
2.width:宽度
3.height:高度
4.bgcolor:背景色(tr td也可以用)
5.align:对齐方式(tr td也可以用)
1.tr: 行
2.td: 列
-->
<table border="3px" width="400px" height="100px" bgcolor="crimson" >
<!--第一行-->
<tr bgcolor="blank">
<td>1</td>
<td bgcolor="black">2</td> <!--2的这一个为黑色-->
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

<!--第二行-->
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

<!--第三行-->
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

<!--第四行-->
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

<!--第五行-->
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>

</table>

代码结果如下

表格合并问题:
  1.colspan 跨行
  2.rowspan 跨列
  3.嵌套时候是在一个框框内加一个表格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!--
表格:table
1.colspan 跨行<tr>
2.rowspan 跨列<td>
-->

<table border="1px" width="400px">
<!--第一行-->
<tr>
<td colspan="2">11</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<!--第二行-->
<tr>
<td>21</td>
<td>22</td>
<td>23</td>
<td>24</td>
<td>25</td>
</tr>
<!--第三行-->
<tr>
<td>31</td>
<td>32</td>
<td rowspan="2" colspan="2" align="center">
<!--嵌套表格-->
<table border="1px" width="100%" height="100%">
<tr>
<td> <img src="../../img/10.jpg" width="46px"/></td>
</tr>
</table>
</td>
<td>35</td>
</tr>
<!--第四行-->
<tr>
<td rowspan="2">41</td>
<td>42</td>
<td>45</td>
</tr>
<!--第五行-->
<tr>
<td>52</td>
<td>53</td>
<td>54</td>
<td>55</td>
</tr>
</table>

代码结果如下


反射

一、反射
  动态获取信息以及动态调用对象的方法的功能。能够对任意一个类,获取类的所有属性和方法

  • 解剖类—–>获取字节码文件对象

三种获取字节码对象方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 反射联系;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class的方法forName
Class clazz1=Class.forName("反射联系.Main"); //需要包.类名
//2. 为类的静态方法
Class clazz2=Main.class;
//3. 创建对象调用方法getClass方法
Main m=new Main();
Class clazz3=m.getClass();
System.out.println(clazz1==clazz2);//判断三个是不是相等
System.out.println(clazz3==clazz2);
//结果都是true
}
}

  • 反射(Class.forName(“包.类名”))

榨汁机榨汁的案例
分别有 水果(Fruit) 苹果(Apple) 香蕉(Banana) 桔子(Orange) 榨汁(squeeze)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Main {
public static void main(String[] args) throws Exception {
Juicer j=new Juicer();//购买榨汁机
j.run(new Apple()); //榨汁机炸苹果
//j.run(new Orange()x);//Apple a=new Orange(); 类型不匹配
j.run(new Orange());
}
}

class Apple {
public void squeeze() {
System.out.println("榨出苹果汁儿");
}
}

class Orange {
public void squeeze() {
System.out.println("榨出橘子汁儿");
}
}
//榨汁机负责榨水果
class Juicer{
public void run(Apple a)//榨苹果
{
a.squeeze();
}

public void run(Orange o)//榨橘子
{
o.squeeze();
}
}

  但是这种问题就是如果有很多水果就不停的要建立水果类,然后不停的在Juicer类中写出榨水果的run方法比较麻烦,所以我们要考虑使用多态的方法Fruit实现squeeze()榨汁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Main {
public static void main(String[] args) throws Exception {
Fruit f=new Apple();//多态 -----左父右子
f.squeeze();
}
}

interface Fruit{ //实现榨汁
public void squeeze();
}


class Apple implements Fruit{//所有要用的类实现接口Fruit

public void squeeze() {
System.out.println("榨出苹果汁儿");
}
}

class Orange implements Fruit{
public void squeeze() {
System.out.println("榨出橘子汁儿");
}
}

class Juicer{
public void run(Fruit f)//run对象为接口的 f
{
f.squeeze();
}
}

而使用反射
主要是添加一个文件名为config.properties(里面写包名.你需要的实现的类名)

1
2
3
4
5
6
7
8
9
10
11
12

public class Main {
public static void main(String[] args) throws Exception {
//使用反射配置文件
BufferedReader br=new BufferedReader(new FileReader("config.properties"));//字符流
Class c=Class.forName(br.readLine()); //读取一行(\u53CD\u5C04\u8054\u7CFB.Apple)
Fruit f=(Fruit)c.newInstance(); //---父类引用指向子类对象
//建立榨汁机对象然后调用run方法run(f)
Juicer j=new Juicer();
j.run(f);//执行结果为 榨出苹果汁
}
}

  • 通过反射—>带参构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 反射联系;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main2 {
public static void main(String[] args) throws Exception{
Class clazz=Class.forName("反射联系.Main");//拿到字节码
//无参构造创建对象
Main m=(Main) clazz.newInstance();
System.out.println(m);

Constructor c=clazz.getConstructor(Fruit.class);//获取有参构造
Main m1=(Main) c.newInstance("Apple");//有参构造创建对象
System.out.println(m1);
}
}

  • 通过反射成员变量(私有/共有)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.lang.reflect.Constructor;
public class Main2 {
public static void main(String[] args) throws Exception{
Class clazz=Class.forName("反射联系.Main");//拿到字节码
Constructor c=clazz.getConstructor(String.class);//获取有参构造getConstructor
Main m1=(Main) c.newInstance("Apple");//有参构造创建对象

//1 共有的public
java.lang.reflect.Field f1=clazz.getField("Fruit");//获取姓名字段------getField
f1.set(m1,"Orange");//将苹果apple改成orange

//2.私有的private
java.lang.reflect.Field f2=clazz.getDeclaredField("Fruit");//暴力反射获取姓名字段-----getDeclaredField
f2.setAccessible(true); //去除私有private权限
f2.set(m1,"Orange");//将苹果apple改成orange
}
}

  • 通过反射方法(有参/无参)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Main3 {
public static void main(String[] args) throws Exception{
Class clazz=Class.forName("反射联系.Main");//拿到字节码
Constructor c=clazz.getConstructor(String.class);//获取有参构造getConstructor
Main m1=(Main) c.newInstance("Apple");//有参构造创建对象

//无参方法
Method m3=clazz.getMethod("squeeze");
m3.invoke(m3);

//有参方法
Method m2=clazz.getMethod("squeeze",int.class);
m2.invoke(m2);

}
}

二、越过泛型检查
  泛型只在编译期间有效,运行期(字节码文件)会被擦除掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Main4 {
public static void main(String[] args) throws Exception{
ArrayList<Integer> l=new ArrayList<Integer>();
l.add(111);
l.add(222);
Class c=Class.forName("java.util.ArrayList"); //拿到字节码文件
Method m=c.getMethod("add",Object.class); //更改add方法
m.invoke(l,"abc");调用Method方法的invoke修改方法添加add
System.out.println(l); //------>[111, 222, abc]
}
}

三、指定值(setProperty)
  public void setProperty(Object o,String qian,Object hou):把o对象中名字是qian的属性值—>改成hou

稀疏数组

稀疏sparsearray数组

  • 适用前提:大部分元素为0/是同一个值的数组。
  • 处理方法:
    • 第一行记录数组(几行+几列+几个不同值)
    • 依次列出不同值元素(所在行+所在列+值)

稀疏数组举例:


二维数组与稀疏数组转换

  1. 遍历二维数组–>有效数据的个数sum
  2. 根据sum可以创建稀疏数组sparseArr int[sum+1]3
  3. 二维数组有效数据存到稀疏数组

转换代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int[][] a=new int[11][11];//原始数组为11*11的矩阵
a[1][2]=1;//数组里面的第二行第三列数字为1
a[2][3]=2;//数组里面的第三行第四列数字为2
System.out.println("原始数据:");
for(int i=0;i<a.length;i++)
{
for(int j=0;j<a[i].length;j++)
{
System.out.printf("%d\t",a[i][j]);
}
System.out.println();
}

//二维数组a-----稀疏数组b
int sum=0;//记录一共多少个非0数
for(int i=0;i<a.length;i++)
{
for(int j=0;j<a[i].length;j++)
{
if(a[i][j]!=0)//非0的情况就加一
{
sum++;//记录一共有多少非0数
}
}
}
System.out.println("一共有"+sum+"个非0数字");
int[][] b=new int[sum+1][3];//sum行列每一个行列值 每个数都是三列元素
b[0][0]=11;//第一行放数组的行+列+sum
b[0][1]=11;
b[0][2]=sum;
int flag=1;//下标变换存数
for(int i=0;i<a.length;i++)
{
for(int j=0;j<a[i].length;j++)
{
if(a[i][j]!=0)
{

b[flag][0]=i;
b[flag][1]=j;
b[flag][2]=a[i][j];
flag++;//只能等这一行放入了再flag++
}
}
}
//输出稀疏数组
System.out.println("稀疏数组:");
for(int i=0;i<sum+1;i++)
{
for(int j=0;j<3;j++)
{
System.out.printf("%d\t",b[i][j]);
}
System.out.println();
}

//稀疏数组b-----二维数组c
int[][] c=new int[b[0][0]][b[0][1]];
int flag1=1;
for(int i=1;i<b.length;i++)
{
c[b[i][0]][b[i][1]]=b[i][2];
}
//输出c数组
System.out.println("输出原数组:");
for(int i=0;i<c.length;i++)
{
for(int j=0;j<c[i].length;j++)
{
System.out.printf("%d\t",c[i][j]);
}
System.out.println();
}
}
}

#

网络课设

一、题目和要求
题目:协议分析软件开发及网络协议分析
(1)教学内容
网络协议分层结构,网络协议工作过程,协议数据单元结构,协议分析,协议设计,协议分析软件开发。
(2)教学要求
理解网络协议的层次结构及网络协议的工作过程,掌握网络协议的分析方法及网络协议的设计与应用。


二、了解必须的协议首部格式

  • IP协议(首部格式):

IP协议,又译为网际协议或互联网协议,是用在TCP/IP协议簇中的网络层协议。IP协议位于TCP/IP协议的网络层,位于同一层次的协议还有下面的ARP和RARP以及上面的ICMP(Internet控制报文协议)和IGMP(Internet组管理协议)。除了ARP和RARP报文以外的几乎所有的数据都要经过IP协议进行传送。ARP和RARP报文没有封装在IP数据报中,而ICMP和IGMP的数据则要封装在IP数据报中进行传输。由于IP协议在网络层中具有重要的地位,TCP/IP协议的网络层又被称为IP层。

  • TCP协议(首部格式):

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
当应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,TCP则把数据流分割成适当长度的报文段,最大传输段大小(MSS)通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)限制。之后TCP把数据包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。

  • UDP协议(首部格式):

  UDP协议概述:一种无连接协议,提供无连接服务,在传送数据之前不需要先建立连接;传送的数据单位协议是 UDP 报文或用户数据报。对方的运输层在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 是一种最有效的工作方式。UDP 用户数据报是在运输层的端到端抽象的逻辑信道中传送的。


三、实现思路

  1. JAVA语言虽然在TCP/UDP传输方面给予了良好的定义,但对于网络层以下的控制,却是无能为力的。JPCAP扩展包弥补了这一点,jPcap是一个可以让java工作在链路层的类库;当然,它底层还是使用了本机API通过Jini调用,在javaAPI中得到数据。JPCAP实际上并非一个真正去实现对数据链路层的控制,而是一个中间件,JPCAP调用wincap/libpcap,而给JAVA语言提供一个公共的接口,从而实现了平台无关性。
  2. 通过使用主函数main去调用分析函数analyzePacke()和其他的方法去解决各个功能。通过while循环不断的输入选项去完成选择。通过线程抓获去获取数据包(用数组去存放数据包),然后重写run()方法去获取数据包。
  3. 最后可以通过break跳出menu菜单(或者选择停止抓数据包)。

四、具体实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
import jpcap.*;
import jpcap.packet.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public class Test{
//定义默认最大抓包数
private static final int max = 1000;
//显示所有网络设备信息
private static void showDeviceList(NetworkInterface[] devices) {
//展示当前主机设备信息
System.out.println("本机上所有适配器如下:");
for (int i = 0; i < devices.length; i++)
{
//网络适配器名称(循环输出所有的适配器)
System.out.println("Adapter " + (i + 1) + "(名称)" + devices[i].description);

//MAC地址
System.out.print(" MAC address(MAC地址): ");
for (byte b : devices[i].mac_address) //用:隔开输出16进制
{
System.out.print(Integer.toHexString(b & 0xff) + ":");
}
System.out.println();

//IP地址
for (NetworkInterfaceAddress a : devices[i].addresses) //调用方法输IP地址
{
System.out.println(" IPv6/IPv4 address(IP地址): " + a.address);
}
System.out.println();
}
}

//网络接口监听
private static JpcapCaptor openDevice(NetworkInterface[] devices, int choice) throws java.io.IOException //抛出异常
{
JpcapCaptor captor = null;
Try
{
captor = JpcapCaptor.openDevice(devices[choice], 65535, false, 3000);
//方法中的变量为一次性抓65535的长度,超时时间为3000ms
}
catch (IOException e)
{
e.printStackTrace();//打印异常信息在程序中出错的位置以及原因
System.out.println("打开网络接口失败!");
}
return captor;
}

//数据包捕获线程(Thread)
private static class AThread implements Runnable
{
Thread thread;
JpcapCaptor captor;
Packet[] packet;

//线程中断标志
volatile boolean cancel;
AThread(JpcapCaptor captor) throws IOException{
this.captor = captor;//用this调用数据
this.packet = new Packet[max];//用this调用数据
this.cancel = false;//用this调用数据
thread = new Thread(this);//用this调用数据
}

@Override //重写线程中的run方法
public void run() {
packet = new Packet[max];
for(int i = 0; i < max && cancel == false; i++){
packet[i] = captor.getPacket();//调用getpacket()方法获取数据包
}
}
//设置中断的方法(主要用于选项2的操作)
public void cancel()
{
cancel = true;
}

public Packet[] getPacket()
{
return packet;//获取数据包
}

}



private static Packet[] readPacket(JpcapCaptor captor, String filename)
{
Packet[] packet = new Packet[max];//定义一个packet数组去存取数据包
try
{
captor = JpcapCaptor.openFile(filename);
}
catch (IOException e)
{
e.printStackTrace();
}

for(int i = 0;;i++){
packet[i] = captor.getPacket();
if(packet[i] == null)
break;
}
return packet;
}

//按键5的功能去实现展示当前有多少数据包
private static void analyzePacket(Packet[] packet)
{
//定义三个泛型去动态存取数据包个数
ArrayList<UDPPacket> udpPacketArray = new ArrayList<UDPPacket>();
ArrayList<ARPPacket> arpPacketArray = new ArrayList<ARPPacket>();
ArrayList<TCPPacket> tcpPacketArray = new ArrayList<TCPPacket>();
int count, count1, count2, count3,;
count = count1 = count2 = count3 = 0;
for(int i = 0; packet[i] != null && i < max; i++) //循环存各个类型的
{
count++;
if (packet[i] instanceof UDPPacket)//如果获取的数据包属于UDPPacket包
{
UDPPacket udp = (UDPPacket) packet[i];
udpPacketArray.add(udp);
count1++;
}
else
if(packet[i] instanceof ARPPacket)//如果获取的数据包属于ARPPacket包
{
ARPPacket arp = (ARPPacket) packet[i];
arpPacketArray.add(arp);
count2++;
}
else
if(packet[i] instanceof TCPPacket)//如果获取的数据包属于TCPPacket包 {
TCPPacket tcp = (TCPPacket) packet[i];
tcpPacketArray.add(tcp);
count3++;
}
}
System.out.println();//换行方便查看
System.out.println("所有数据包数:" + count);
System.out.println("UDP数据包数:" + count1);
System.out.println("ARP数据包数:" + count2);
System.out.println("TCP数据包数:" + count3);
}

//此方法循环输出每个包的信息
private static void showPacket(Packet[] packet)
{
for(int i = 0; packet[i] != null && i < max-1; i++)
{
System.out.println("Packet " + (i+1) + " : " + packet[i]);
}
}

//按键4显示数据包详细情况
private static void showPacketDetail(Packet[] packet)
{
System.out.print("输入你想查看的包序号");
Scanner input=new Scanner(System.in);
int num=input.nextInt();//输入你要选择看的包序号
num=num-1;
for(int i = 0; packet[i] != null && i < max-1; i++)
{
if(i==num) //如果选的那个数字和循环的符合的话去判断是哪个数据包
{
if(packet[i] instanceof UDPPacket) // 如果获取的数据包属于UDPPacket包
{
UDPPacket udp = (UDPPacket) packet[i];
HexBinaryAdapter head = new HexBinaryAdapter();
String str = head.marshal(udp.header);
int tou = (str.charAt(29)-48)*4*2;//主要用于判断推送字节输出检验和
System.out.println("Packet " + (i+1) + " : UDP" );
System.out.println(" 数据 : " + str);
System.out.println("**********ip首部*********");
System.out.println(" 版本:IPv"+ udp.version);
System.out.println(" 首部长度:" + str.substring(29,30));
System.out.println(" 区分服务: 0");
System.out.println(" 总长度:" + udp.length);
System.out.println(" 标识:" + udp.ident);
System.out.println(" MF: " + udp.more_frag);
System.out.println(" DF: " + udp.dont_frag);
System.out.println(" 片偏移:" + udp.offset);
System.out.println(" 生存时间:" + udp.hop_limit);
System.out.println(" 源 ip地址 : " + udp.src_ip.toString());
System.out.println(" 目的ip地址 : " + udp.dst_ip.toString());
System.out.println("**********数据部分*********");
System.out.println(" 源端口 : " + String.valueOf(udp.src_port));
System.out.println(" 目的端口 : " + String.valueOf(udp.dst_port));
System.out.println(" 长度 : " + String.valueOf(udp.length));
System.out.println(" 校验和 : +str.substring(28+tou+12,28+tou+16));
System.out.println();
}
else
if(packet[i] instanceof TCPPacket) //如果获取的数据包属于TCPPacket包
{
TCPPacket tcp = (TCPPacket) packet[i];//TCP
HexBinaryAdapter head = new HexBinaryAdapter();//转成16进制
String str = head.marshal(tcp.header);
int tou = (str.charAt(29)-48)*4*2;//主要用于判断推送字节输出检验和
System.out.println("Packet " + (i+1) + " : TCP" );
System.out.println(" 数据 : " + str);
System.out.println("**********ip首部*********");
System.out.println(" 版本:IPv"+ tcp.version);
System.out.println(" 首部长度:" + str.substring(29,30));
System.out.println(" 区分服务: 0");
System.out.println(" 总长度:" + tcp.length);
System.out.println(" 标识:" + tcp.ident);
System.out.println(" MF: " + tcp.more_frag);
System.out.println(" DF: " + tcp.dont_frag);
System.out.println(" 片偏移:" + tcp.offset);
System.out.println(" 生存时间:" + tcp.hop_limit);
System.out.println(" 源 ip地址 : " + tcp.src_ip.toString());
System.out.println(" 目的ip地址 : " + tcp.dst_ip.toString());
System.out.println("**********数据部分*********");
System.out.println(" 源 ip地址 : " + tcp.src_ip.toString());
System.out.println(" 目的ip地址 : " + tcp.dst_ip.toString());
System.out.println(" 源端口 : " + String.valueOf(tcp.src_port));
System.out.println(" 目的端口 : " + String.valueOf(tcp.dst_port));
System.out.println(" 序号:" + tcp.sequence);
System.out.println(" 确认号:" + tcp.ack_num);
System.out.println(" 数据偏移:" + tcp.offset);
System.out.println(" 保留:0");
System.out.println(" 紧急URG:" + tcp.urg);
System.out.println(" 确认ACK:" + tcp.ack);
System.out.println(" 推送PSH:" + tcp.psh);
System.out.println(" 复位RST:" + tcp.rst);
System.out.println(" 同步SYN:" + tcp.syn);
System.out.println(" 终止FIN:" + tcp.fin);
System.out.println(" 窗口:" + tcp.window);
System.out.println(" 检验和:" + str.substring(28+tou+32,28+tou+36));
System.out.println(" 紧急指针:" + tcp.urgent_pointer);
System.out.println(" 选项:" + tcp.option);
System.out.println();
}
else
if(packet[i] instanceof ARPPacket)//如果获取的数据包属于ARPPacket包
{
ARPPacket arp = (ARPPacket) packet[i];//ARP
HexBinaryAdapter head = new HexBinaryAdapter();//转成16进制
String str = head.marshal(arp.header);
byte[] b = new byte[4];
String s1 = "";
String s2 = "";
b = arp.target_protoaddr;
s1 += String.valueOf((b[0] & 0xff) + "." + ( b[1] & 0xff) + "." + (b[2] & 0xff) + "." + (b[3] & 0xff));
b = arp.sender_protoaddr;
s2 += String.valueOf((b[0] & 0xff) + "." + ( b[1] & 0xff) + "." + (b[2] & 0xff) + "." + (b[3] & 0xff));
for (byte d : arp.sender_hardaddr)
{
System.out.print(Integer.toHexString(d & 0xff) + ":");
}
for (byte e : arp.target_hardaddr)
{
System.out.print(Integer.toHexString(e & 0xff) + ":");
}
System.out.println("Packet " + (i+1) + " : ARP" );
System.out.println(" 数据 : " + str);
System.out.println(" Hardware type: " + arp.hardtype);
System.out.println(" protocol type : " + arp.prototype);
System.out.println(" Hardware size : " + arp.hlen);
System.out.println(" protocol size : " + arp.plen);
System.out.print(" sender MAC address: ");
for (byte d : arp.sender_hardaddr)
{
System.out.print(Integer.toHexString(d & 0xff) + ":");
}
System.out.println();
System.out.println(" sender ip address: " + s2);
System.out.print(" target MAC address: " );
for (byte e : arp.target_hardaddr)
{
System.out.print(Integer.toHexString(e & 0xff) + ":");
}
System.out.println();
System.out.println(" target ip address: " + s1);

System.out.println();
}
}
}
}


public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
//数组存放数据包
Packet[] packet = new Packet[max];
//初始化数据包捕获的线程
AThread t = null;
//获取网络设备并显示
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
showDeviceList(devices);
//输入选择的监控的网卡
System.out.print("选择需要监听的设备序号:");
int card = scanner.nextInt();
card = card -1;
System.out.println();

//打开选择的网络接口
JpcapCaptor captor = openDevice(devices, card);

menu:
while(true) {
//功能菜单
System.out.println("选择功能编号:");
System.out.println("1. 捕获当前网卡的数据包");
System.out.println("2. 停止捕获网络数据包");
System.out.println("3. 显示当前捕获的数据包");
System.out.println("4. 查看数据包详细信息");
System.out.println("5. 分析数据包的协议分布");
System.out.println("6. 退出!");
System.out.print("你的选择:");
//用户选择
int choice = scanner.nextInt();//输入选择项

//功能执行(通过选各个类型去决定下一步干什么)
switch (choice){
case 1: System.out.println("正在捕获数据包...");//选择去抓包抓数据包
t = new AThread(captor);
Thread capThread = new Thread(t);
capThread.start();
break;
case 2: System.out.println("已停止捕获数据包");//停止抓数据包
t.cancel();//调用停止方法cancel将布尔值的中断标志改为false
break;
case 3: System.out.println("显示当前捕获的数据包如下:");//如果线程为空那就显示失败
if(t == null)
{
System.out.println("数据包捕获未开启,失败!");
break;
}
packet = t.getPacket(); //调用获得数据包的方法
showPacket(packet);//调用展示数据包的方法
break;
case 4: System.out.println("数据包详细分析:");//调用展示数据包细节的方法
showPacketDetail(packet);
break;
case 5: System.out.println("数据包的协议分布如下:");
analyzePacket(packet);//调用分析数据包的方法
break;
case 6: System.out.println("退出!");//想要结束就break跳出menu
break menu;
}
System.out.println();//分隔一行为了方便查看
}

//关闭线程和抓包
captor.close();
}
}

五设计中的问题以及心得

  1. 一开始不知道怎么去抓获数据包就去上网搜查和查看数据最终发现可以使用JPCAP扩展,jPcap是一个可以让java工作在链路层的类库调用wincap/libpcap,而给JAVA语言提供一个公共的接口,从而使用插件最终得到抓获数据包的操作。
  2. 第一步讨论得到后,与组员讨论最终决定使用主函数调用每个功能模块,既使用模块化设计方法得到功能。但是不知道怎么去抓获数据包之后存储,询问其他同学和查看网络API之后发现可以通过数组去存储数据包,从而用循环去不断的操作。
  3. 可以在抓取和实现功能后,发现还需要界面设计达到分析协议软件开发,或者通过GUI图形界面显示。
  4. 我和组员分工之后,我主要去实现主函数和TCP协议的分析部分,主要是和组员的代码要能配对起来比较麻烦,最终不断地调试和改bug得到了结果。
  5. 抓获数据包最终分析的时候,首部其他内容都可以得到调用方法得到结果,但是TCP和IP检验和部分就比较麻烦,我们最终决定使用推算字节数得到答案。
    以IP检验和为例:
    创建一个 HexBinaryAdapter的对象将二进制数组转换为十六进制字符串:
1
HexBinaryAdapter head =  new HexBinaryAdapter();

定义一个字符串存首部长度head的16进制信息:

1
String str = head.marshal(udp.header);

计算IP首部部分的长度:

1
2
3
4
5
6
7
8
	int tou = (str.charAt(29)-48)*4*2;
```
因为IP之前的MAC帧就有14个字节,而一个字节就是2位十六进制,然后通过减去0的ASCII码转换成相对应的16进制数字。
而为了获得检验和就需要转字节之后加上之前的12个字节,从13到16就是Ip数据包的检验和部分
System.out.println(" 校验和 : " +str.substring(28+tou+12,28+tou+16));
6. 课设答辩的时候薛老师很负责的提出了我们组的设计存在的问题是:一次性显示了所有数据包的信息但是不能去挑选具体的数据包去分析是哪个协议。->于是我们在判断语句中输入要挑选的数据包,然后去判断是否存在这个数据包,然后输出分析数据包的内容。
具体解决问题的代码如下(附录中也有):
在循环中输入想查看的包的序号
System.out.print("输入你想查看的包序号");
    Scanner input=new Scanner(System.in);
    int num=input.nextInt();//输入你要选择看的包序号
    num=num-1;
    for(int i = 0; packet[i] != null && i < max-1; i++) 

{
if(i==num) //如果选的那个数字和循环的符合的话去判断是哪个数据包
{
…//中间的就是确定存在,然后去判断是哪个协议的数据包从而输出
}
}

```

webserver

一、反射:
  反射是框架设计的灵魂(框架是半成品软件,可以在框架的基础上进行软件开发,简化编码)。
将类的各个组成部分封装成其他对象

TCP编程

一、TCP(面向连接的通信)
  TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分客户端(Client)和服务器(Server)。
二、通信步骤(通信原理)

  1. 服务器端先启动
  2. 客户端请求–>服务器端
  3. 客户端< – >服务器端【逻辑连接(有一个对象)
  4. 逻辑连接含有客户端提供的** IO对象 **(字节流对象)

** IO对象 **
TCP连接的示意图:

  • 注意:
  1. 服务器必须明确和哪个客户端交互,而且需要多个IO流对象。
  • 服务器端方法 ** accpet **,客户端获取 –> 客户端对象。
  • 服务器(没有IO流) –> 服务器获取请求客户端对象Socket
  • (服务器用的客户端的IO流交互)
  • 服务器使用客户端的字节输入流(读取)客户端发送的数据
  • 服务器使用客户端的字节输出流(回写)给客户端数据

Server(服务器)

1
2
3
4
1.指定端口 使用ServerSocket创建服务器
2.阻塞式等待连接accept
3.操作:使用输入输出流操作
4.释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args)throws IOException {
System.out.println("----Server(服务器)----");
//1.指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8088);
//2.阻塞式等待连接accept
Socket client=server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:使用输入输出流操作
DataInputStream shuru=new DataInputStream(client.getInputStream());/用DataInputStream输入流
String data=shuru.readUTF();//输入
//4.释放资源
shuru.close();//释放shuru
client.close();//释放Client
server.close();//释放server服务器对象
}
}

Client(客户端)

1
2
3
1.建立连接:使用Socket建立窗户段+服务的地址和端口
2.第一步连接好了直接操作:使用输入输出流操作
3.释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException{
System.out.println("----Client(客户端)----");
//1.建立连接:使用Socket建立窗户段+服务的地址和端口
Socket client=new Socket("localhost",8088);//创建client对象去接收服务器的东西
//2.第一步连接好了直接操作:使用输入输出流操作
DataOutputStream shuchu=new DataOutputStream(client.getOutputStream());//用DataOutputStream输出流
String data="hello";//输出一个字符串 hello
shuchu.writeUTF(data);//shuchu写入
shuchu.flush();
//3.释放资源
shuchu.close();//释放输出
client.close(); //释放client对象
}
}

三、TCP文件上传
  在前面的基础上只需要将传输的数据做更改即可达到单向传输!

Client(客户端)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException{
System.out.println("----Client(客户端)----");

BufferedReader console=new BufferedReader(new InputStreamReader(System.in));//用BufferedReader类型去创建输入用户名和密码
System.out.println("请输入用户名");
String uname=console.readLine();
System.out.println("请输入密码");
String upassword=console.readLine();

//1.建立连接:使用Socket建立窗户段+服务的地址和端口
Socket client=new Socket("localhost",8088);
//2.第一步连接好了直接操作:使用输入输出流操作
DataOutputStream shuchu=new DataOutputStream(client.getOutputStream());//输
shuchu.writeUTF("uname="+uname+"&"+"upassword="+upassword);
shuchu.flush();
//3.释放资源
shuchu.close();
client.close();
}
}

Server(服务器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args)throws IOException {
System.out.println("----Server(服务器)----");
//1.指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8088);
//2.阻塞式等待连接accept
Socket client=server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:使用输入输出流操作
DataInputStream shuru=new DataInputStream(client.getInputStream());//输入流
String datas=shuru.readUTF();

//分析数据
String[] dataArray=datas.split("&");//用&分割
for(String info:dataArray)//增强型for循环输出
{
String[] userinfo=info.split("=");
System.out.println(userinfo[0]+"-->"+userinfo[1]);

}

//4.释放资源
shuru.close();
client.close();
server.close();
}
}

代码结果如下:

  • 客户端的截图:

  • 服务器的截图:

传输协议(UDP)

一、网络爬虫(虚拟)

  1. 获取URL
    URL url=new URL("https://www.jd.com")
  2. 下载资源
  3. 分析
  4. 处理

代码实现(取京东的数据):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class pachongle{
public static void main(String[] args) throws Exception {//抛出异常
URL url=new URL("https://www.jd.com");//获取京东URL
InputStream is=url.openStream();//输入流
BufferedReader br=new BufferedReader(new InputStreamReader(is,"UTF-8"));/京东的是UTF-8
String msg=null;//定义一个字符串msg
while(null!=(msg=br.readLine()))
{
System.out.println(msg);//输出
}
br.close();//一定要记得br对象用完之后关闭

}
}

代码结果如下:
京东的所有源文件(浏览器中的源文件)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class pachongle{
public static void main(String[] args) throws Exception {
URL url=new URL("https://www.dianping.com");//换成了点评网址
InputStream is=url.openStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is,"UTF-8"));
String msg=null;
while(null!=(msg=br.readLine()))
{
System.out.println(msg);
}
br.close();

}
}
  • 提示403问题(有权限)通过简单的抓取无法做到
1
2
3
4
5
6
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.dianping.com
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at pachong.pachongle.main(pachongle.java:9)
  • 模拟浏览器HttpURLConnection
  1. //get从服务器获取资源
    对象.setRequestMethod("GET");
  2. //post往服务器上推数据
    对象.setRequestProperty("XXXXX");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class pachongle{
public static void main(String[] args) throws Exception {
URL url=new URL("https://www.dianping.com");
//用HttpURLConnection类
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
//get从服务器获取资源
conn.setRequestMethod("GET");
//post往服务器上推数据
conn.setRequestProperty("XXXXX");

BufferedReader br=new BufferedReader(new InputStreamReader(conn.InputStream(),"UTF-8"));
String msg=null;
while(null!=(msg=br.readLine()))
{
System.out.println(msg);
}
br.close();

}
}

二、UDP(非面向连接)

  1. 使用基于UDP协议的Socket网络编程实现
  2. 不需要利用IO流实现数据传输
  3. 每个数据发送单元被统一封装成数据包。发送方将数据包发送到网络中,数据包在网络中寻找目的地。

UDP基本概念:

  • DatagramSocket:用于发送/接收数据包的套接字
  1. send(DatagramPacket 对象)
  2. receive(DatagramPacket 对象)
  3. close()
  • DatagramPacket:数据包
    主要创建对象new(容器,0,长度)

发送端(client)

1
2
3
4
5
1.使用DatagramSocket端口创建接收端
2.准备数据(转成字节数组)
3.封装成DatagramPacket包裹(指定目的地)
4.发送包裹send(DatagramPacket p)
5.释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class udpClient{
public static void main(String[] args) throws Exception{
System.out.println("发送方启动中...");
//1.使用DatagramSocket端口创建接收端
DatagramSocket client=new DatagramSocket(8888);
//2.准备数据(转成字节数组)
String data="西安工程大学";
byte[] datas=data.getBytes();
//3.封装成DatagramPacket包裹(指定目的地)
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",9999));
//4.发送包裹send(DatagramPacket p)
client.send(packet);
//5.释放资源
client.close();

}
}

接收端(server)

1
2
3
4
5
1.使用DatagramSocket端口创建接收端
2.准备容器,封装成DatagramPacket包裹
3.阻塞式接收包裹receive(DatagramPacket p)
4.分析数据 getData()/getLength()
5.释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class udpServer{
public static void main(String[] args) throws Exception {
System.out.println("接收方启动中...");
//1.使用DatagramSocket端口创建接收端
DatagramSocket server=new DatagramSocket(9999);//发送的包里面也必须是9999
//2.准备容器,封装成DatagramPacket包裹
byte[] container=new byte[1024*60];
DatagramPacket packet=new DatagramPacket(container,0,container.length);
//3.阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet);
//4.分析数据 getData()/getLength()
byte[] datas=packet.getData();
int len=packet.getLength();
System.out.println(new String(datas,0,len));
//5.释放资源
server.close();

}
}

代码结果如下:


  • 多次交流的前提:(多次输入)

发送端(client)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class udpClient{
public static void main(String[] args) throws Exception{
System.out.println("发送方启动中...");
//1.使用DatagramSocket端口创建接收端
DatagramSocket client=new DatagramSocket(8888);
//2.准备数据(转成字节数组)
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));//使用这个控制台输入

while(true) //多了一个while循环
{
String data=reader.readLine();//对象不断输入

byte[] datas=data.getBytes();
//3.封装成DatagramPacket包裹(指定目的地)
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",9999));
//4.发送包裹send(DatagramPacket p)
client.send(packet);
if(data.equals("bye")) //当输入的数据为bye时输出
{
break;
}
}
//5.释放资源
client.close();
}
}

接收端(server)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class udpServer{
public static void main(String[] args) throws Exception {
System.out.println("接收方启动中...");
//1.使用DatagramSocket端口创建接收端
DatagramSocket server=new DatagramSocket(9999);//发送的包里面也必须是9999
//2.准备容器,封装成DatagramPacket包裹
while(true) { //比之前的多了一个while循环
byte[] container=new byte[1024*60];
DatagramPacket packet=new DatagramPacket(container,0,container.length);
//3.阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet);
//4.分析数据 getData()/getLength()
byte[] datas=packet.getData();
int len=packet.getLength();
String data=new String(datas,0,len);
System.out.println(data);
if(data.equals("bye")) //当最后的数据为bye就结束
break;
}
//5.释放资源
server.close();

}
}

三、UDP多次交流(多线程)

TalkReceive类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class TalkReceive implements Runnable {
private DatagramSocket server;
//1.
public TalkReceive(int port) {
try {
server=new DatagramSocket(port);//抛出异常
} catch (SocketException e) {
e.printStackTrace();
}
}

//2.

@Override
public void run() { //将封装udpServer中的while循环内容
while(true) {
byte[] container=new byte[1024*60];
DatagramPacket packet=new DatagramPacket(container,0,container.length);
//3.阻塞式接收包裹receive(DatagramPacket p)
try {
server.receive(packet);
//4.分析数据 getData()/getLength()
byte[] datas=packet.getData();
int len=packet.getLength();
String data=new String(datas,0,len);
System.out.println(data);
if(data.equals("bye"))
{
break;
}

} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

//5.释放资源
server.close();
}

}
}

TalkSend类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/*
* 封装updTalkClient
*/
public class TalkSend implements Runnable{
//1
private DatagramSocket client;
private BufferedReader reader;
private String toIP;//对方地址
private int toPort;//对方端口
public TalkSend(int port,String toIP,int toPort) {
this.toIP=toIP;
this.toPort=toPort;
try {
client=new DatagramSocket(port);
reader=new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
//2
@Override
public void run() { //直接将updTalkClient中的while拿过来
while(true)
{
String data;
try {
data = reader.readLine();
byte[] datas=data.getBytes();
//3.封装成DatagramPacket包裹(指定目的地)
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));//将本地主机换成toIP和toPort端口
//4.发送包裹send(DatagramPacket p)
try {
client.send(packet);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
if(data.equals("bye"))
{
break;
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

//5.释放资源
client.close();
}
}


}

然后构建两个对话类

TalkTeacher类

1
2
3
4
5
6
7

public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkReceive(9999)).start();//接收9999
new Thread(new TalkSend(5555,"localhost",8888)).start();//8888发送
}
}

TalkStudent类

1
2
3
4
5
6
7
8
9
/*
* 加入多线程,实现双向交流 模拟在线咨询
*/
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7777,"localhost",9999)).start();//9999发送
new Thread(new TalkReceive(8888)).start();//接收8888
}
}

四、TCP的使用(面向连接可靠)
相对于UDP而言,TCP是一种面向连接的通讯方式,提供一种可靠的方法。

,