计算机基础网站知识总结
OSI互联参考模型
其有7层构成,自下而上分别为物理层、数据链路层、网络层、传输层、会话层、表现层、应用层;则发送进程自上而下处理,接收进程自下而上处理;具体处理流程如下:
TCP/IP参考模型
该参考模型将公用的OSI 7层参考模型细化为4层,自下而上为链路层、网络层、传输层、应用层;具体的架构图如下:
说说TCP三次握手
第一次握手:客户端发送一个SYN包,携带seq=x,SYN=1;客户端进入SYN_SEND状态
第二次握手:服务端接受到客户端的SYN包后,确认可以传输发送一个SYN+ACK包,携带seq=y,ack=x+1,ACK=1,SYN=1;服务端进去SYN_RECEIVERD
第二次握手:客户端发送ACK包,确认链接,ACK=1,seq=x+1,ack=y+1,至此客户端服务端都进入ESTAB-LISHED(已获确认的)状态
示意图如下:
说说为什么TCP要进行三次握手
TCP三次握手是客户端与服务端都要进行sequence number的初始化以及ACK包的确认
TCP的报文组成
源端口:TCP发送报文客户端端口
目的端口:TCP报文接受端端口
序号:报文分片生成的序列号
确认号:该值为接收报文序列号+1
数据偏移:4bit,其长度实际上指示了数据区在报文段中的起始偏移值。
保留:为将来定义新的用途保留,现在一般置0
tcp flags:标示该Tcp报文的功能
窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535。
校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
紧急指针:只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
TCP选项:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
TCP flag的参数涵义如下
- TCP flag
- URG :紧急指针标志
- ACK:确认序号标志
- PSH:push标志
- RST:重置链接标志
- SYN:同步序号,用于建立链接过程
- FIN:finish标记,用于释放链接
TCP的四次挥手
第一次挥手:客户端发送一个FIN报文,携带FIN=1,seq=u;的关闭报文,客户端进入FIN-WAIT1
第二次挥手:服务端接收到客户端关闭报文后,发送一个携带ACK=1,ack=u+1,seq=v的确认报文,服务器进入CLOSE-WAIT
第三次挥手:服务端发送一个FIN报文,携带FIN=1,ACK=1,ack=u+1,seq=v的关闭报文,用来关闭server到client的数据传送, 服务端进入LAST_ACK状态
第四次挥手:客户端发送一个ACK报文,携带ACK=1,seq=u+1,ack=v+1,至此链接关闭,双方均进入close状态
四次挥手的具体流程图如下
为什么要进行4次挥手
因为TCP是全双工通讯,客户端与服务端都要发送FIN包与ACK包,故各需要俩次
UDP报文的组成
源端口号和目的端口号如上和TCP的相同。
UDP长度:UDP报文的字节长度(包括首部和数据)。
UDP校验和: 检验UDP首部和数据部分的正确性。
- UDP特点
- 面向非连接
- 不维护链接状态,支持向多个客户端发送相同的数据
- 数据包报头只有8个字节,额外开销小
- 吞吐量只受限于数据生成速率、传输速率以及机器性能
- 尽最大努力交付,不保证可靠交付、不需要维持复杂的链接状态表
- 面向报文,无需对传送数据进行拆分与合并
TCP与UDP的区别
面向链接 VS 无连接
可靠性:TCP发送报文更可靠
有序性:TCP发送报文有序
速度:udp更快
量级:TCP是重量型的,UDP为轻量型,发送的数据少
HTTP与HTTPS
HTTP简介
超文本传输协议的特点
- 支持客户端/服务端模式
- 简单快速
- 灵活
- 无连接
- 无状态
HTTP的请求结构
一次HTTP请求由请求行、请求头部、空行、请求数据四部分组成
服务器响应消息由状态行、响应头部、空行、响应正文四部分组成
Http请求响应的步骤
- 客户端链接到web服务器,本质上是建立一个tcp套接字链接
- 发送http请求
- 服务器接受请求并返回http响应
- 客户端浏览器解析相应的html内容
- 释放tcp链接
在浏览器地址栏键入URL,按下回车键后执行的步骤
- DNS域名解析,找到访问服务器的Ip地址
- 建立tcp套接字链接
- 发送http请求报文
- 服务端返回http响应报文
- 客户端浏览器渲染返回的html
- 关闭tcp链接
GET与POST的区别
从三个层面上讲
- http报文层面:GET将请求信息放在URL中,POST将请求放在请求报文中
- 数据库层面:GET请求是符合幂等性与安全性,POST不符合
- 其他层面:GET可以被缓存、被存储,而POST不行
Cookie与Session的区别
Cookie简介
- 是由服务器发送给客户端的特殊信息,以文本信息存储在客户端
- 客户端再次发送请求会将Cookie回发
- 服务器端接手后,会解析Cookie将生成与客户端相同的数据
Session简介
- 服务器端的机制,在服务器端保存信息
- 解析客户端请求并操作Session_id,按需保存状态信息
Session的实现方式
- 使用Cookie来实现
- 使用URL回写来实现
Cookie与Session的区别
- Cookie存放在客户端,Session存放在服务端
- Session比Cookie更安全
- 若考虑减轻服务器端负担,推荐使用Cookie
Http与Https的区别
Https是引入加密SSL的Http请求
- 加密的方式
- 对称加密:加密与解密都使用同一密钥
- 非对称加密: 加密使用的密钥与解密使用的密钥是不一致的
- 哈希算法: 将任意长度的信息转换为固定长度的值,算法不可逆
- 数字签名: 证明某个消息或者文件是某人发出/认同的
Https数据传输流程
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以证书的形式回发给浏览器
- 浏览器验证证书的合法性,并结合证书中的公钥加密信息并发送给服务端
- 服务器使用私钥解密信息,验证哈希,并将相应消息加密发送给浏览器端
- 浏览器解析信息,并对消息进行验真,之后进行加密交互数据
Socket实例
TCP
tcp Server
package com.bdcloud.tcp;
import com.bdcloud.thread.DuaClientWithSocket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/***
* Tcp Server
*
*/
public class TcpServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(6758);
//接收到客服端连接
while (true) {
Socket accept = serverSocket.accept();
new Thread(new DuaClientWithSocket(accept)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
tcp client
package com.bdcloud.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/***
* client
*/
public class TcpClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",6758);
//往服务端写数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello Tcp Server".getBytes());
//接收服务端返回数据
InputStream inputStream = socket.getInputStream();
byte[] buff = new byte[1024];
inputStream.read(buff,0,buff.length);
System.out.println(new String(buff));
} catch (IOException e) {
e.printStackTrace();
}
}
}
tcp server 处理线程
package com.bdcloud.thread;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DuaClientWithSocket implements Runnable{
private Socket socket;
@Override
public void run() {
try {
//获取输入流
InputStream inputStream = socket.getInputStream();
byte[] buff = new byte[1024];
int ch = inputStream.read(buff, 0, buff.length);
System.out.println("服务端接受的数据="+new String(buff,0,ch));
//往客户端写入
OutputStream outputStream = socket.getOutputStream();
String result = "服务器返回接收到的长度="+ch;
outputStream.write(result.getBytes());
inputStream.close();
outputStream.close();
//socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP
UDP server
package com.bdcloud.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/***
* Udp Server
*
*/
public class UdpServer {
public static void main(String[] args) {
//服务端接受客户端发送的数据报文
try {
DatagramSocket socket = new DatagramSocket(6895);
byte[] acpet = new byte[1024];
DatagramPacket packet = new DatagramPacket(acpet,0,acpet.length);
socket.receive(packet);
byte[] packetData = packet.getData();
//接收到的数据
String content = new String(packetData,0,packet.getLength());
System.out.println(content);
//返回给接受端
byte[] result = String.valueOf(content.length()).getBytes();
DatagramPacket clientPacket = new DatagramPacket(result,result.length,packet.getAddress(),packet.getPort());
socket.send(clientPacket);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP client
package com.bdcloud.udp;
import java.io.IOException;
import java.net.*;
/***
* client
*/
public class UdpClient {
public static void main(String[] args) {
try {
//设置客户端监听接口
DatagramSocket socket = new DatagramSocket();
byte[] bytes = "hello udp".getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,6895);
socket.send(packet);
byte[] accept = new byte[1024];
DatagramPacket reciverdata = new DatagramPacket(accept,0,accept.length);
socket.receive(reciverdata);
byte[] data = reciverdata.getData();
System.out.println("客户端接受的数据="+new String(data,0,reciverdata.getLength()));
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}