一、什么是网络模型?
网络模型是对计算机网络的一种抽象描述和规范,用于解释网络中数据的传输、通信协议的工作方式以及网络中各个组件之间的关系。
常见的网络模型有 OSI 参考模型(Open Systems Interconnection Reference Model)和 TCP/IP 模型。OSI 参考模型将网络通信分为七层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。每一层都有特定的功能和职责。
TCP/IP 模型则通常分为四层,即网络接口层、网际层、传输层和应用层。
二、tcp协议和udp协议的区别?
TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)主要有以下区别:
-
连接性:
- TCP 是面向连接的协议,在通信之前需要建立连接,通信结束后要释放连接。
- UDP 是无连接的协议,不需要事先建立连接,直接发送数据。
-
可靠性:
- TCP 提供可靠的数据传输,通过确认、重传、拥塞控制等机制保证数据的正确和有序到达。
- UDP 不保证数据的可靠交付,可能会出现丢包、乱序等情况。
-
有序性:
- TCP 数据按发送顺序到达接收端。
- UDP 不保证数据的顺序。
-
首部开销:
- TCP 首部开销较大,因为包含了更多的控制信息来保证可靠性。
- UDP 首部开销小,只有 8 个字节。
-
应用场景:
- TCP 适用于对数据准确性和顺序要求较高的应用,如文件传输、电子邮件、远程登录等。
- UDP 适用于实时性要求高、对少量丢包不敏感的应用,如视频直播、在线游戏、语音通话等。
三、使用UDP协议完成客户端和服务器端的通信案例
package com.daofeng;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* @Title: UdpClient.java
* @Description: 使用UDP协议完成客户端和服务器端的通信
* @author HeLijin
* @date 2024-11-04 13:54:33
*/
//先写服务器端,再写客户端
public class UdpClient {
public static void main(String[] args) throws IOException {
System.out.println("udp客户端启动连接...");
//不传入端口号,表示是客户端
DatagramSocket ds = new DatagramSocket();
String str = "刀锋网络";
byte[] strBytes = str.getBytes();
DatagramPacket dp = new DatagramPacket(strBytes, strBytes.length,InetAddress.getByName("127.0.0.1"), 8080);
ds.send(dp);
ds.close();
}
}
package com.daofeng;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* http 浏览器 访问不了udp协议,因为 http底层采用的是tcp协议
*/
// udp服务器端
public class UdpServer {
public static void main(String[] args) throws IOException {
//1.ip地址+端口号
System.out.println("udp服务已经启动...");
//创建服务器端 端口号,默认使用本机Ip地址
DatagramSocket ds = new DatagramSocket(8080);
//服务器端接收客户端1024个字节
byte[] bytes = new byte[1024];
//定义数据包
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//接收客户端请求,将数据封装到数据包
//receive() 方法 如果客户端不向服务器端发送请求,就一直阻塞
ds.receive(dp);
System.out.println("来源IP地址:" + dp.getAddress() +",请求来源端口号:" +dp.getPort());
String result = new String(dp.getData(),0,dp.getLength());
System.out.println(result);
//关掉服务器端端口号
ds.close();
}
}
四、使用 tcp协议 完成客户端和服务器端的通信
package com.daofeng;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Title: TcpClient.java
* @Description: tcp协议 完成客户端和服务器端的通信
* @author HeLijin
* @date 2024-11-04 16:03:23
*/
class TcpServer {
public static void main(String[] args) throws IOException {
System.out.println("tcp协议服务器端启动...");
//缓存线程池创建线程
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//创建服务器端连接
ServerSocket serverSocket = new ServerSocket(8080);
try {
// 设置多个客户端访问,支持并发访问
while(true) {
//接收客户端请求 有阻塞功能
Socket accept = serverSocket.accept();
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
InputStream inputStream = accept.getInputStream();
//将字节流转换成String类型
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
String result = new String(bytes, 0, len);
System.out.println(Thread.currentThread().getName() + "服务器端接收到客户端内容:" + result);
//响应客户端
OutputStream outputStream = accept.getOutputStream();
outputStream.write("this is daofeng.com".getBytes());
} catch (Exception e) {
// TODO: handle exception
}
}
});
}
} catch (Exception e) {
// TODO: handle exception
} finally {
serverSocket.close();
}
}
}
//客户端
public class TcpClient {
public static void main(String[] args) throws IOException{
System.out.println("socket tcp客户端启动...");
//创建socket客户端
Socket socket = new Socket("127.0.0.1", 8080);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("我是刀锋网络忠实粉丝...".getBytes());
socket.close();
}
}
五、彩蛋
TCP 协议在建立连接时采用三次握手,在关闭连接时采用四次挥手。
采用三次握手成功之后,才开始进行数据传输。
在 TCP 三次握手过程中,相关参数的变化如下:
第一次握手:
- 客户端发送一个 SYN 包给服务器,其中序列号(sequence number)通常是一个随机生成的数,假设为 J。
第二次握手:
- 服务器收到客户端的 SYN 包后,向客户端发送一个 SYN + ACK 包。其中,序列号为服务器随机生成的一个数,假设为 K,确认号(ACK number)设置为客户端发送的序列号 J + 1,即 ACK = J + 1。
第三次握手:
- 客户端收到服务器的 SYN + ACK 包后,向服务器发送一个 ACK 包。序列号为客户端第一次发送的序列号 J + 1,确认号为服务器第二次发送的序列号 K + 1,即 ACK = K + 1。