当前位置: 首页 > news >正文

【JavaEE】UDP数据报套接字编程

目录

网络编程基础

基本概念

发送端和接收端

请求和响应

客户端和服务端

常见的客户端服务端模型

Socket套接字

TCP/UDP特点

Java数据报套接字通信模型(UDP通信)

UDP数据报套接字编程

DatagramSocket

1.类定义

2.构造方法

3.核心方法

4.特性说明

DatagramPacket

1.类定义

2.构造方法

3.关键方法

4.数据处理

协作机制

1.发送端流程

2.接收端流程

创建回显服务器--客户端


网络编程基础

网络编程,是指网络上的主机,通过不同的进程,以编程的方式实现网络通信(数据交互)

当然,我们主要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程

特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程

网络上的不同主机,基于网络来传输数据资源:

·进程A:编程来获取网络资源

·进程B:编程来提供网络资源

基本概念

发送端和接收端

在一次网络数据传输时:

发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机

接收端:数据的接受方进程,称为接收端。接受端主机即网络通信中的目的主机

收发端:发送端和接受端两端,也简称为收发端

注意:发送端和接受端是相对的。如下图:

请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输

第一次:请求数据的发送

第二次:响应数据的发送

客户端和服务端

客户端:获取服务的一方进程,称为客户端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务

对于服务端来说,一般都是提供服务:

1.客户端获取服务资源(请求)--》服务端返回服务资源(响应)

2.客户端保存资源在服务端(请求服务端保存用户资源)--》服务端返回处理结果(响应)

常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:

1.客户端先发送请求到服务端

2.服务端根据请求数据,执行相应的业务处理

3.服务端返回响应,发送业务处理结果

4.客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

Socket套接字

概念:Socket(套接字)是网络通信的核心编程接口,它是操作系统提供的、基于TCP/IP协议的网络通信的基本操作单元,用于实现进程间网络通信的底层工具。无论是Web服务器、即使通讯软件还是P2P应用,底层都依赖Socket实现数据传输。基于Socket套接字的网络程序开发就是网络编程。

socket在英文上有“插座”的意思,插座上有不同规格的插孔,我们将插头插入到对应的插孔当中就能实现电流的传输

在进行网络通信时,客户端就相当于插头,服务端就相当于一个插座,但服务端上可能会有多个不同的服务进程(多个插孔),因此当我们在访问服务端时,需要指明服务进程的端口号(对应规格的插孔),才能享受对应服务进程的服务

作用:Socket建立在TCP/IP协议之上,用于管理连接和传输数据。它允许在两台计算机之间通过网络进行数据交换

分类

Socket套接字主要针对传输层协议分为如下三类:

流套接字:使用传输层TCP协议

对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收

数据报套接字:使用传输层UDP协议

对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1字节

原始套接字:用于自定义传输层协议,用于读写内核没有处理的IP协议数据(简单了解即可)

TCP/UDP特点

TCP:有连接、可靠传输、面向字节流、有接收缓冲区,也有发送缓冲区、大小不限

UDP:无连接、不可靠传输、面向数据报:有接受缓冲区,无发送缓冲区、大小受限(一次最多传输64k)

后续会详细讲解其中细节

Java数据报套接字通信模型(UDP通信)

对于UDP协议来说,具有无连接,面向数据报的特性,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报

java中使用UDP协议通信,主要基于DatagramSocket类来创建数据报套接字,并使用DatagramPacket作为发送或接收的UDP数据报。
 

在Java网络编程中,DatagramSokcetDatagramPacket是UDP通信的核心搭档,它们的关系可以比喻为"邮局"和"信件"

1.DatagramSocket(邮局):

·是实际进行网络通信的端点,相当于一个能收发电报的邮局

·负责绑定端口、建立通信通道

·提供send()方法和receive()方法实现数据报传输

2.DatagramPacket(信件):

·是要传输的数据载体,相当于装有具体内容的信封

·包含:

        ·数据缓冲区(信件内容)

        ·目标地址和端口(发送时的收件人信息)

        ·源地址和端口(接收时的发件人信息)

3.协作关系:

·发送过程:

1.将数据放入DatagramPacket(写信)

2.通过DatagramSocket的send()方法投递(寄信)

·接收过程

1.准备空的DatagramPacket作为容器(准备空信封)

2.通过DatagramSocket的receive方法收取(收信)

3.从DatagramPacket中提取数据和来源信息(拆信阅读)

4.依赖关系:

·DatagramSocket必须依赖DatagramPacket来传输实际数据

·没有DatagramPacket,DatagramSocket就像没有信封的邮局,无法完成通信任务

这种分工使得UDP通信既灵活又高效:DatagramSocket处理网络通信细节,DatagramPacket专注数据封装,二者配合实现了无连接的数据报传输模式

对于一次发送及接收UDP数据报的流程如下:

以上只是一次发送端的UDP数据报发送,及接受端的数据报接收,并没有返回的数据。也就是只有请求,没有响应。

对于一个服务端来说,重要的是提供多个客户端的请求处理及响应,流程如下:

·

我们上述学习了UDP数据报的发送和接收的大致流程。现在我们学习如何用代码完成上述网络通信

UDP数据报套接字编程

我们在这里详细介绍DatagramSocket和DatagramPacket--UDP通信的核心搭档

DatagramSocket

1.类定义

public class DatagramSocket extends Object

表示用于发送和接收数据报的套接字,基于UDP协议实现

2.构造方法

1.DatagramSocket():创建绑定到本地任意可用端口的套接字

2.DatagramSocket(int port):创建绑定到指定本地端口的套接字

3.DatagramSocket(int port,InetAddress addr):创建绑定到指定端口和本地地址的套接字

3.核心方法

注意:在send和receive方法中,传参为DatagramPacket类型。即:封装的数据报(在后续的DatagramPacket会学习到)

4.特性说明

·无连接:通信前无需建立连接,直接发送数据报

·不可靠传输:不保证数据送达,可能丢包或乱序

·高效性:适合实时性要求高的场景(如视频流传输)

DatagramPacket

1.类定义

public final class DatagramPacket extends Object

表示数据报,用于封装要发送或接收的数据

2.构造方法

3.关键方法

这里的getData()方法获取到的数据报字节数组是包含数据的

4.数据处理

·发送端:需明确指定目标地址和端口

·接受端:通过getData()和getLength()提取有效数据

·缓冲区管理:接收时需重置缓冲区长度(setLength() )以准备接收新数据

协作机制

1.发送端流程

1.创建DatagramSocket实例

2.准备发送数据并转换为字节数组

3.创建DatagramPacket,指定目标地址和端口

4.调用socket.send(packet)发送数据

5.关闭套接字(可选,长期运行的服务器通常不关闭)

代码示例

// 创建发送端套接字
DatagramSocket senderSocket = new DatagramSocket();

// 准备数据
String message = "Hello UDP Server!";
byte[] data = message.getBytes();

// 创建目标地址
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 9876;

// 构造数据包
DatagramPacket sendPacket = new DatagramPacket(
    data, 
    data.length, 
    serverAddress, 
    serverPort
);

// 发送数据
senderSocket.send(sendPacket);

2.接收端流程

1.创建DatagramSocket并绑定端口

2.创建DatagramPacket作为接收容器

3.循环调用socket.receive(packet)等待数据

4.解析数据报内容并处理

5.关闭套接字

代码示例

// 创建接收端套接字
DatagramSocket receiverSocket = new DatagramSocket(9876);

// 准备接收缓冲区
byte[] buffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);

while(true) {
    // 接收数据(阻塞方法)
    receiverSocket.receive(receivePacket);
    
    // 解析数据
    String receivedData = new String(
        receivePacket.getData(), 
        0, 
        receivePacket.getLength()
    );
    
    // 获取发送方信息
    InetAddress clientAddress = receivePacket.getAddress();
    int clientPort = receivePacket.getPort();
    
    // 处理数据(示例:打印信息)
    System.out.println("Received from " 
        + clientAddress.getHostAddress() 
        + ":" + clientPort 
        + " - " + receivedData);
    
    // 重置缓冲区
    receivePacket.setLength(buffer.length);
}

创建回显服务器--客户端

回显服务器--客户端:客户端发送什么请求,服务器便返回什么

回显服务器UdpEchoServer

public class UdpEchoServer {
    //回显服务器
    //创建UDP套接字
    private DatagramSocket socket=null;
    //构造方法
    public UdpEchoServer(int port) throws SocketException {
        socket=new DatagramSocket(port);
    }
    //启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            //循环一次,就相当于处理一次请求
            //处理请求的过程,典型的服务器都是分成三个步骤的
            //1.读取请求并解析
            //DatagramPacket表示一个UDP数据报。此处传入的字节数组,就保存了UDP的载荷部分(数据)
            DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);//用套接字socket接收数据报
            //把读取到的二进制数据转成字符串。
            String request=new String(requestPacket.getData(),
            0,
            requestPacket.getLength());

            //2.根据请求,计算响应
            //但是我们这里是回显服务器,这个环节相当于省略了
            String response=process(request);

            //3.把响应返回给客户端
            //根据response构造Data'gramPacket,发送给客户端
            //注意这里使用的是getBytes方法,传入字节数组以及其数组长度
            //还需要传递 指定的目的ip和目的端口--接收到的请求中包含
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),
            response.getBytes().length,
            requestPacket.getSocketAddress());

            socket.send(responsePacket);
            //4.打印日志
            System.out.printf("[%s:%d]req:%s,resp:%s\n",
            requestPacket.getAddress().toString(),
            requestPacket.getPort(),
            request,response);
        }
    }

    //根据请求得到响应
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server=new UdpEchoServer(9090);
        server.start();
    }
}

回显客户端UdpEchoClient

public class UdpEchoClient {
    //回显客户端--UDP
    private DatagramSocket socket=null;

    //UDP本身不保存对端的信息,我们这里在代码中可以自己手动保存
    private String serverIp;
    private int serverPort;

    public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
        this.serverIp=serverIp;
        this.serverPort=serverPort;
        socket=new DatagramSocket();
    }

    public void start() throws IOException {
        Scanner sc=new Scanner(System.in);
        while(true){
            //1.从控制台读取用户输入的内容
            System.out.println("请输入要发送的内容:");
            if(!sc.hasNext()){//如果无输入,则结束循环
                break;
            }
            String request=sc.next();
            //2.把请求发送给服务器--->构造DatagramPacket对象
            //注意:构造过程中,不光需要载荷(数据),还需设置服务器的IP(目的ip)和端口(目的端口)
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),
            request.getBytes().length,
            InetAddress.getByName(serverIp),
            serverPort);

            //3.发送数据报
            socket.send(requestPacket);
            //4.接收服务器的响应
            DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            //5.将从服务器读取的数据进行解析,并打印下来
            String response=new String(responsePacket.getData(),
            0,
            responsePacket.getLength());
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client=new UdpEchoClient("127.0.01",9090);
        client.start();
    }
}

运行结果:

服务器:

客户端:

相关文章:

  • 傅里叶变换C++实现方式
  • [C++]C++入门篇 2025最新版
  • Leetcode 寻找两个正序数组的中位数
  • CAM获取操作(程序组)的加工时间
  • 短视频团队架构工作流程---2025.3.30 李劭卓
  • python: DDD+ORM+pyQt6 using MySql
  • 用 Python 实现机器学习小项目:从入门到实战
  • Pyside6 信号与槽
  • 阿里云下一代可观测时序引擎-MetricStore 2.0
  • CPM:大规模生成式中文预训练语言模型
  • 从头开始运行一个yolo11的分类模型
  • MySQL响应慢是否由堵塞或死锁引起?
  • 端到端自动驾驶VLA模型:技术解析与模型设计
  • PostgreSQL数据库迁移到Docker拉取的pg镜像中的
  • 3.30 学习总结 Java 常用API+图形化界面
  • Linux系统中修改主机名及设置固定IP地址保姆级教程
  • UE5学习笔记 FPS游戏制作29 更换武器时更换武器的图标
  • 大模型LLMs基于Langchain+FAISS+Ollama/Deepseek/Qwen/OpenAI的RAG检索方法以及优化
  • Java图片加水印 实战demo
  • Linux中逻辑卷的使用、扩容与磁盘配额
  • 建设一个网站要钱吗/天津seo推广服务
  • 做产品推广有网站比较好的/网站策划是干什么的
  • 保定网站制作套餐/腾讯企点app下载安装
  • 免费网站的资源可以发公众号吗/会计培训班
  • 北京网站制作建设公司/大型网站制作
  • 课桌公司网站建设/小白如何学电商运营