1.网络模型
1.1.七层模型
1.物理层
定义各种设备标准,如网线的接口类型,管线的接口类型,各种传输介质的传输速率等。
2.数据链路层
定义了如何让格式化的数据进行传输,以及如何控制对物理介质的访问。这一层通常还提供错误检测和修正,以确保数据的可靠传输。
3.网络层
将数据传输到目标地址;目标地址可以使多个网络通过路由器连接而形成的某一个地址,主要控制寻找地址和路由选择,网络层还可以实现拥塞控制,网络互联等功能。
4.传输层
提供端到端的服务,可以实现流量控制,负载均衡,这层使用的设备是主机本身。 tcp和udp作用在传输层。
5.会话层
维持通信,http
6.表示层
格式转换,压缩数据
7.应用层
http,ftp,smtp,https,即直接面向用户的程序或服务。
1.2五层模型
1.物理层 2.链路层 3.网络层 4.传输层 5.应用层
2.TCP/IP协议
2.1TCP报文
名称 | 解释 |
---|
序号(Seq) | 序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。 | 确认号(Ack) | 确认号占32位,客户端和服务器端都可以发送,Ack=Seq+1 | 标志位 | 每个标志位占用1bit,共有6个。URG,ACK,PSH,PST.SYN,FIN | SYN | 建立一个连接 | FIN | 断开一个连接 |
2.2 TCP三次握手
那么为什么要进行3次握手,2次不行吗? 三次握手的目的:为了防止已经失效的连接请求报文段突然又传送到了服务端,因而产生了错误。 这么说,可能还是比较官方,那么我们更加通俗的来解释:
- 第一次握手,客户端向服务器发送请求,服务器收到请求,说明客户端的发送能力和服务器的接收能力都正常。
- 第二次握手,服务器向客户端发送请求,客户端收到请求,说明服务器的发送能力正常。但是此时并不能确定客户端是否收到,即客户端的接收能力是否正常
- 那么这个时候就需要第三次握手了,客户端向服务器发送请求,服务器收到请求,说明客户端的接收能力也正常。
2.3 TCP的四次挥手
为什么客户端在TIME-WAIT阶段要等待2msl?
MSL是报文的最大生存时间,2MSL即2倍报文最大的存活时间。
为的是确定服务器端是否收到客户端发出的ACK确认报文。若服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文。
为什么连接的时候是3次挥手,而关闭的时候是4次握手?
因为当服务端接收到客户端SYN请求连接报文后,可以直接发送seq和ack报文。其中ack报文是用来回应的,seq报文是用来同步的。所以3次握手即可。但是关闭连接时,但服务端接收到客户端FIN报文时,很可能不会立即关闭socket,所以只能先回复一个ack报文,告诉客户端:“你发的报文我收到了”。只有当服务端将所有报文都发送完,才能发送FIN报文,因此不能一起发送,故需要四次握手。
3.Socket 编程
3.1TCP
Socket: 套接字,抽象对象,通过Socket的编程,完成网络编程。
public class TCPServer {
public static void main(String[] args) throws Exception {
final int PORT = 9090;
ServerSocket server = new ServerSocket(PORT);
System.out.println("服务器启动成功....");
boolean f = true;
while (f) {
Socket socket = server.accept();
InputStream stream = socket.getInputStream();
InputStreamReader in = new InputStreamReader(stream,"utf-8");
char[] buffer = new char[64];
while(in.read(buffer)!=-1) {
String line= new String(buffer);
System.out.print(line);
Arrays.fill(buffer, (char)0);
}
System.out.println();
}
server.close();
}
}
public class TCPClient {
public static void main(String[] args) throws Exception {
final int PORT = 9090;
final String HOST = "127.0.0.1";
Scanner sc = new Scanner(System.in);
Socket socket = new Socket(HOST, PORT);
while (true) {
System.out.print("请问输入: ");
String s = sc.nextLine();
OutputStream out = socket.getOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(out);
ow.write(s);
ow.flush();
socket.close();
}
}
}
3.2UDP
public class UDPServer {
public static void main(String[] args) throws IOException {
final int PORT = 9090;
DatagramSocket socket = new DatagramSocket(PORT);
System.out.println("接收端启动......");
byte[] buffer =new byte[1024];
DatagramPacket packet =
new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String msg = new String(packet.getData());
System.out.println("[接收端] 收到数据>>>" + msg);
socket.close();
}
}
|