文章目录
1、实现会话跟踪
下面哪项技术可以用在WEB开发中实现会话跟踪实现? session 、Cookie 、地址重写 、隐藏域
HTTP是“无状态”协议:客户程序每次读取 Web 页面,都打开到 Web 服务器的单独的连接,并且,服务器也不自动维护客户的上下文信息。即使那些支持持续性 HTTP 连接的服务器,尽管多个客户请求连续发生且间隔很短时它们会保持 socket 打开,但是,它们也没有提供维护上下文信息的内建支持。上下文的缺失引起许多困难。例如,在线商店的客户向他们的购物车中加入商品时,服务器如何知道购物车中己有何种物品呢?类似地,在客户决定结账时,服务器如何能确定之前创建的购物车中哪个属于此客户呢?这些问题虽然看起来十分简单,但是由于 HTTP 的不足,解答它们却异常复杂困难。对于这个问题,存在 3 种典型的解决方案:
Cookie(结合session使用)
可以使用 cookie 存储购物会话的 ID;在后续连接中,取出当前的会话 ID,并使用这个 ID 从服务器上的查找表(lookup table)中提取出会话的相关信息。 以这种方式使用 cookie 是一种绝佳的解决方案,也是在处理会话时最常使用的方式。但是,sevlet 中最好有一种高级的 API 来处理所有这些任务,以及下面这些冗长乏味的任务:从众多的其他cookie中(毕竟可能会存在许多cookie)提取出存储会话标识符的 cookie;确定空闲会话什么时候过期,并回收它们;将散列表与每个请求关联起来;生成惟一的会话标识符。
URL 重写
采用这种方式时,客户程序在每个URL的尾部添加一些额外数据。这些数据标识当前的会话,服务器将这个标识符与它存储的用户相关数据关联起来。 URL重写是比较不错的会话跟踪解决方案,即使浏览器不支持 cookie 或在用户禁用 cookie 的情况下,这种方案也能够工作。URL 重写具有 cookie 所具有的同样缺点,也就是说,服务器端程序要做许多简单但是冗长乏味的处理任务。即使有高层的 API 可以处理大部分的细节,仍须十分小心每个引用你的站点的 URL ,以及那些返回给用户的 URL。即使通过间接手段,比如服务器重定向中的 Location 字段,都要添加额外的信息。这种限制意味着,在你的站点上不能有任何静态 HTML 页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须使用 servlet 或 JSP 动态生成。即使所有的页面都动态生成,如果用户离开了会话并通过书签或链接再次回来,会话的信息也会丢失,因为存储下来的链接含有错误的标识信息。
隐藏的表单域
HTML 表单中可以含有如下的条目:
这个条目的意思是:在提交表单时,要将指定的名称和值自动包括在 GET 或 POST 数据中。这个隐藏域可以用来存储有关会话的信息,但它的主要缺点是:仅当每个页面都是由表单提交而动态生成时,才能使用这种方法。单击常规的超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用于一系列特定的操作中,比如在线商店的结账过程。
2、什么是HTTP协议
- 它是一种超文本传输协议(HTTP),它允许讲超文本标记语言(HTML)文档从WEB服务器传送到客户端服务器
- 属于应用层的面向对象的协议,由于简捷、快速的方式,适用于分布式超媒体信息系统。他于1990年提出,经过几年的使用与发展,得到不断地完善和扩展
- HTTP是构建在TCP/IP协议之上的,是TCP/IP协议的一个子集
3、什么是Web
- WEB是一种基于超文本和HTTP的,全球的,动态交互的,跨平台的分布式图形信息系统
- 简历在Internet上的一种网络服务,为浏览器在Internet上查找和浏览信息提供了图形化的,易于访问的直观页面,其中的文档以及超级链接将Internet上的信息节点组织成一个互为关联的网络结构
4、TCP/IP协议
- TCP/IP协议其实是一系列与互联网相关联的协议集合起来的总称
- 分层管理是TCP/IP协议的重要特征
5、TCP/IP协议族分层
- 应用层、传输层、网络层和数据链路层
- 应用层:一般是我们编写的应用程序,决定了向用户提供的应用服务 。应用层可以通过系统调用与传输层进行通信如:FTP、DNS、HTTP
- 传输层:通过系统调用向应用层提供处于网络连接中的两条计算机之间的数据传输功能
- 有两个性质不同的协议:TCP和UDP
- 网络层:用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(传输路线)达到对方计算机并把数据包传输给对方
- 链路层:链路层用来处理连接网络的硬件部分,把偶哦控制操作系统、硬件设备驱动
6、HTTP数据传输过程
7、传输层-TCP三次握手
- 使用TCP协议进行通信的双方必须先建立连接,然后才能开始传输数据。为了确保i连接双方可靠性,在双方建立连接时,TCP协议采用了三次握手策略
- 第一次握手:客户端发送带有SYN标志的连接请求报文段,然后进入SYN_SEND状态,等待服务端的确认。
- 第二次握手:服务端接受到客户端的SYN报文段后,需要发送ACK信息对这个SYN报文断进行确认的同时还要发送自己的SYN的请求信息。服务端会将上述的信息放到一个报文段(SYN+ACK报文段)中,一并发送给客户端,此时服务端将会进入SYN_RECV状态
- 第三次握手:客户端接收到服务端的SYN+ACK报文段后会向服务端发送ACK确认报文段,这个报文段发送完毕后,客户端和服务端都进入ESTABLISHED状态,完成TCP三次握手
8、DNS
- 通常我们访问一个网站,使用的是主机名或者域名来进行访问的。因为相对于IP地址(—组纯数字),域名更容易让人记住。但TCP/IP协议使用的是IP地址进行访问的,所以必须有个机制或服务把域名转换成IP地址。DNS服务就是用来解决这个问题的,它提供域名到IP地址之间的解析服务。
9、HTTP事务处理过程
当客户端访问Web站点时,首先会通过DNS服务查询到域名的IP地址。然后浏览器生成HTTP请求,并通过TCP/IP协议发送给Web服务器。Web服务器接收到请求后会根据请求生成响应内容,并通过TCP/IP协议返回给客户端。
10、URL和URI
URI:
- 一个紧凑的字符串用来标示抽象或物理资源
- URI可以进一步被分为定位符、名字或两者都是
- URI可以分为URL、URN或同时具备locators和names特性的一个东西
- URN作用好像一个人的名字,URL就像一个人的地址
- 换句话说:URN确定了东西的身份,URL提供了找到它的方式
URL、URN、URI
- URL是URI的一种,但是不是所有的URI都是URL
- URI换和URL最大的区别是"访问机制"
- URN是唯一标识的一部分
11、HTTP请求报文分析
报文头:
- 通用报文头
- 请求报文头
- 响应报文头
- 实体报文头
在HTTP1.1里一共规范了47种报文头
12、HTTP响应报文分析
13、请求方法
13.1 GET
- GET方法用来请求访问已被URI识别的资源
- 指定的资源经服务器端解析后返回相应内容
- 浏览器默认就是GET
13.2POST
- POST与GET功能类似,一般用来传输实体的主体
- POST方法的主要目的不是获取响应主题的内容
13.3PUT
- 从客户端向服务器传送的数据取代指定的文档的内容
- PUT方法与POST方法最大的不同是:PUT是幂等的,而PSOT不是的(创建用POST、更新用GET)
- 因此更多时候将PUT方法作用传输资源
13.4 HEAD
- 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
13.5 DELETE
- 请求服务器删除指定的资源
13.6OPOTIONS
- 用来查询针对请求URI指定的资源支持的方法
13.7 TRACE
- 回显服务器收到的请求,主要用于测试或诊断
- 一般不会用,容易出现安全漏洞
13.8 CONNECT
- 开启一个客户端与所请求资源之间的双向沟通的通道,它可以用来创建隧道
14 、状态码
概念:
- 标识网页服务器超文本传输协议响应状态的3为数字代码
分类:
- 200 OK 请求成功!
- 202 Accepted 已接受,未处理完成
- 206 Partial Content 部分内容,服务器成功处理了部分Get请求
- 301 Moved Permanently 永久移动,请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
- 302 Found 临时移动,与301类似。但资源知识临时被移动。客户端应该继续使用原有URI
- 400 Bad Request 客户端请求的语法错误,服务器无法理解
- 401 Unauthorized 请求要求用户的身份认证
- 403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
- 404 Not Found 服务器无法根据客户端的请求找到页面
- 500 Internal Server Error 服务器内部错误,无法完成请求
- 502 Bad Gateway 充当网关或代理的服务器,从远端服务器接收到了一个无效请求
15、HTTP状态管理
15.1 Cookie
- Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie。
- 客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie—同提交给服务器。服务器检查该Cookie,以此来辨认用户状态
15.2 Session
- Session是另一种记录客户状态的机制,保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上
Session的有效期
- Session超时失效
- 程序调用HttpSession.invalidate()
- 服务器进程被停止
15.3 Cookie与Session对比
- 存放位置不同 :Cookie存放在客户端 Session存放在服务端
- 安全性(隐私策略不同)Session相对于Cookie比较安全
- 有效期上的不同
- 对服务器造成的压力不同 若考虑减轻服务器负担,应当使用Cookie
16、七层
OSI七层:
- 物理层
- 数据链路层
- 传输层
- 会话层
- 表示层
- 会话层
17、TCP四次挥手
-
挥手是为了终止连接
-
第一次挥手: ient发送一个FIN,用来关闭Client到 Server的数据传送,Client进入FIN_WAIT_1状态;
-
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态;
-
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态;
-
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么会有TIME_WAIT状态
- 确保有足够的时间让对方收到ACK包
- 避免新旧连接混淆
为什么需要四次挥手才能断开连接
因为全双工,发送方和接收方都需要FIN报文和ACK报文
18、UDP
UDP特点
- 面向非连接
- 不维护连接状态,支持同时向多个客户端传输相同的消息
- 数据包报头只有8个字节,额外开销小
- 吞吐量只受限于数据生成速率、传输速率以及机器性能
- 尽最大努力交付,不保证可靠性交付,不需要维持复杂的链接状态表
- 面向报文,不对应用程序提交的保温信息进行拆分或者合并
19、TCP 和UDP区别
- 面向连接 vs无连接
- 可靠性 vs不可靠
- 有序性 vs 无序性
- 速度慢 vs 速度快
- 重量级 vs 轻量级
20、TCP的滑动窗口
RTT和RTO
RTT:发送一个数据包到收到对应的ACK,所花费的时间
RTO:重传时间间隔
TCP使用滑动窗口做流量控制与乱序重排
保证TCP的可靠性
保证TCP的流控特性
21、在浏览器地址栏键入URL,按下回车之后经历的流程
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束(可能有keep-alive)
22、Get和POST请求的区别
-
Http报文层面:
- GET将信息存放在URL
- POST放在报文体中
-
数据库层面:
- GET符合幂等性和安全性
- PSOT不符合
-
其他层面:
- GET可以被缓存、被存储
- POST不行
23、Http和Https的区别
- SSL(Security Sockets Layer,安全套接层)
- 为网络通信提供安全及数据完整的一种安全协议
- 是操作系统堆外体统API,SSL3.0更名为TLS
- 采用身份验证和数据加密保证网络通信的安全和数据完整性
- 加密方式
- 对称加密:加密和解密都是用同一个密钥
- 非堆成加密:加密使用的密钥和解密使用的密钥是不相同的
- 哈希算法:将然亦长度信息转换为固定长度的值:MD5
- 数字签名:证明某个消息或者文件是某人发出/认同的
- HTTPS数据传输流程
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以证书的形式回发浏览器
- 浏览器验证证书合法性,并结合证书公钥加密信息发给服务器
- 服务器使用私钥解密,验证哈希,加密响应消息发回浏览器
- 浏览器解密响应消息,并对消息进行验证,之后加密交换数据
- 区别:
- HTTPS需要到CA申请证书,HTTP不需要
- HTTPS密文传输,HTTP明文传输
- 连接方式不同,HTTPS默认使用443端口,HTTP使用80端口
- HTTPS=HTTP+加密+认证+完整性保护,较HTTP安全
- HTTPS真的很安全吗?
- 浏览器默认填充http://,请求需要进行跳转,有被劫持的风险
- 可以使用(HSTS)优化
24、Socket
Socket是对TCP/IP协议的抽象,是操作系统堆外开放的接口
通信流程
编写一个网络应用程序,有客户端与服务器端,客户端向服务器发送一个字符串,服务器收到该字符串后将其打印到命令行上,然后向客户端返回该字符串的长度,最后,客户端输出服务器端返回的该字符串的长度,分别用TCP和UDP两种方式去实现。
方式一:TCP
Server
/**
* @Description:
* @ClassName algorithm
* @Author: 王瑞文
* @Date: 2021/3/11 13:17
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(4539);
//自旋去一直等待并处理客户端发来的请求
while (true) {
//监听端口,知道客户端返回连接信息
Socket socket=serverSocket.accept();
//获取请求信息,执行业务逻辑
new LengthCalculator(socket).start();
}
}
}
处理请求并返回:
/**
* @Description:
* @ClassName algorithm
* @Author: 王瑞文
* @Date: 2021/3/11 13:18
*/
public class LengthCalculator extends Thread {
private Socket socket;
public LengthCalculator(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream os = socket.getOutputStream();//获取socket输入流
InputStream is = socket.getInputStream();//获取socket输出流
int ch = 0;//记录长度
byte[] buffer = new byte[1024];
ch = is.read(buffer);
//接受字节转换成字符串
String content = new String(buffer, 0, ch);
System.out.println(content);
//往输入流写入获得的字符串长度,回发给客户端
os.write(String.valueOf(content.length()).getBytes());
//关闭流和socket
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client
/**
* @Description:
* @ClassName algorithm
* @Author: 王瑞文
* @Date: 2021/3/11 13:20
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 4539);//创建Socket
OutputStream os = socket.getOutputStream();//获取socket输入流
InputStream is = socket.getInputStream();//获取socket输出流
os.write(new String("Hello My 小公主").getBytes());//
int ch = 0;
byte[] buffer = new byte[1024];
ch = is.read(buffer);
String content = new String(buffer, 0, ch);
System.out.println(content);
is.close();
os.close();
socket.close();
}
}
方式二:UDP
服务端
/**
* @Description:
* @ClassName algorithm
* @Author: 王瑞文
* @Date: 2021/3/11 13:20
*/
public class UDPServer {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(4369);
byte[] buff = new byte[100];//存储从客户端接受到的内容
DatagramPacket packet = new DatagramPacket(buff, buff.length);
socket.receive(packet);
byte[] data = packet.getData();//从DatagramPacket对象中获取真正存储的数据
//转换格式
String content = new String(data, 0, packet.getLength());
System.out.println(content);
byte[] sendContent = String.valueOf(content.length()).getBytes();
//从DatagramPacket对象中获取到数据的来源地址与端口号
DatagramPacket packetToClient = new DatagramPacket(sendContent, sendContent.length, packet.getAddress(), packet.getPort());
socket.send(packetToClient);//发送数据给客户端
}
}
客户端
public class UDPClient {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[] buff = "Hello My pig".getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
//封装数据
DatagramPacket packet = new DatagramPacket(buff, buff.length, address, 4369);
socket.send(packet);//发送数据给客户端
byte[] data = new byte[100];
//DatagramPacket封装服务端发送来的数据
DatagramPacket receivedPacket = new DatagramPacket(data, data.length);
socket.receive(receivedPacket);
String content = new String(receivedPacket.getData(), 0, receivedPacket.getLength());
System.out.println(content);
}
}