(Java高级教程)第三章Java网络编程-第三节:UDP数据报套接字(DatagramSocket)编程

news2024/12/23 9:57:01

文章目录

  • 一:Java数据报套接字通信模型
  • 二:相关API详解
    • (1)DatagramSocket
    • (2)DatagramPacket
  • 三:UDP通信示例一:客户端发送什么服务端就返回什么
    • (1)代码
    • (2)效果展示
    • (3)分析

一:Java数据报套接字通信模型

Java UDP通信模型:Java中使用UDP协议通信,主要依靠一下两个类

  • DatagramSocket:创建UDP Socket
  • DatagramPacket:是UDP Socket发送和接受的数据报

一次发送和接收UDP数据报流程如下

在这里插入图片描述

多个请求流程如下

在这里插入图片描述

二:相关API详解

(1)DatagramSocket

DatagramSocket:用于构造UDP Socket,以发送和接收UDP数据报

构造方法如下

方法签名方法说明
DatagramSocket()创建一个UDP数据报 Socket,绑定到本机任意一个随机端口 ,一般用于客户端
DatagramSocket(int port)创建一个UDP数据报 Socket,绑定到本机任意指定端口 ,一般用于服务端

成员方法如下

方法签名方法说明
void receive(DatagramPacket p)从该Socket中接收数据报(如果未收到则会阻塞等待
void send(DatagramPacket p)由该Socket发送数据报(不会阻塞等待,直接发送
void close()关闭此Socket

(2)DatagramPacket

DatagramPacket:是UDP Socket发送和接收的数据报

构造方法如下

方法签名方法说明
DatagramPacket(byet[] buf, int length)用于接收数据报,接收的数据保存在buf数组中,length指定接收长度
DatagramPacket(byet[] buf, int offset, int length, SocketAddress address)用于发送数据报,发送的数据为buf数组,范围为从0到lengthaddress是目的主机的IP和端口号

成员方法如下

方法签名方法说明
InetAddress getAddress()从接收的数据报中获取发送端主机IP地址;或从发送的数据报中获取接收端主机IP地址
int getPort()从接收的数据报中获取发送端主机端口号;或从发送的数据报中获取接收端主机端口号
bye[] getData()获取数据报中的数据

三:UDP通信示例一:客户端发送什么服务端就返回什么

  • 注意:这个功能比较简单,但主要目的是为了演示上面所讲API的用法

(1)代码

服务端IP地址设置为127.0.0.1,也即本地环回,也即自己发自己收,数据会完整走一遍协议

服务端:UDPServer

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPServer {
    // 构造DatagramSocket
    private DatagramSocket socket = null;

    public UDPServer(int port) throws SocketException {
        // 服务端需要绑定一个端口号
        socket = new DatagramSocket(port);
    }

    // 服务端启动
    public void start() throws IOException {
        System.out.println("服务器启动!");
        // 服务端随时等待接收客户端请求
        while (true) {
            /*
                 1. 接受请求并解析
                    构造一个DatagramPacket对象requestPacket用于接受客户端发来的数据报,保存在byte[]
                    为了方便查看信息,需要使用 requestPacket的getData()方法将其转换为String
             */
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            /*
                2. 拿到客户端的请求request后,将其交给一个方法process进行处理,process方法会返回响应response
             */
            String response = process(request);
            /*
                3. 将响应回复给客户端
                   构造一个DatagramPacket对象responsePacket用于给客户端回复响应response ,response是String
                   所以需要使用用getBytes()方法将其转化为byte[]
                   客户端发来的requestPacket数据报中携带有客户端的Ip地址和端口号,使用getSocketAddress()获得
             */
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);

            // 打印信息
            System.out.println("【客户端IP: " + requestPacket.getAddress().toString()
                    + "客户端口号:" + requestPacket.getPort() + "】"
                    + ":\"" + request + "\"" + ", 服务端回复: " + "\"" + response + "\"");
        }
    }

    // 回显服务器,客户端发什么服务端就回复什么
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        // 服务端监听9090端口
        UDPServer server = new UDPServer(9090);
        server.start();
    }
}

客户端:UDPClient

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UDPClient {
    DatagramSocket socket = null;
    // 客户端需要指定好服务端的IP和端口号,然后构建一个Socket地址
    private SocketAddress ADDRESS = null;

    public UDPClient(String serverIP, int serverPort) throws SocketException {
        ADDRESS = new InetSocketAddress(serverIP, serverPort);
        socket = new DatagramSocket();
    }

    // 客户端启动
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            // 1. 读取客户端用户输入
            System.out.print("input: ");
            String request = scanner.next();

            /*
                2. 发送请求给服务端
                   构造一个DatagramPacket对象requestPacket用于给服务端发送数据报,注意需要将String转换为byte[]
                   同时传入服务端的ADDRESS(ip地址和port)
             */
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                   ADDRESS);
            socket.send(requestPacket);

            // 3. 从服务端获取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());

            // 打印信息
            System.out.println("服务端回复:" + response);

        }
    }

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

(2)效果展示

在这里插入图片描述

(3)分析

对于服务端(UDPServer类)

  • 构造方法( public UDPServer(int port)

    • 需要建立一个DatagramSocket并绑定一个指定的端口号port,也即 DatagramSocket socket =new DatagramSocket(port)。服务端绑定端口号的原因是因为程序运行在服务器上是确定的、可控的
  • 服务端处理逻辑(public void start()

    • ①:接受请求并解析

      • 需要构造一个DatagramPacket用于接受客户端发来的数据报,会保存在byte[]中,也即DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096)
      • 接受行为由socket完成,也即socket.receive(requestPacket)
      • 接受到的requestPacket 其类型为byte[],所以需要把它转为String以便于查看,也即String request = new String(requestPacket.getData(), 0, requestPacket.getLength())
    • ②:处理请求

      • 拿到解析后的request后,需要对该request进行处理(交给方法process),不同的业务逻辑会有不同的处理方法。这里我们只是简单的“回显”一下即可,也即客户端发什么服务端就回复什么
    • ③:将处理结果(响应)回复给客户端

      • 需要构造一个DatagramPacket用于给客户端回复响应response,在构造时要将类型为Stringrespnse转化为byte[],同时使用requestPacket.getSocketAddress()获取到客户端的IPport(因为服务端总要知道客户端的具体地址才能发送),也即DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length, requestPacket.getSocketAddress())
      • 发送行为由socket完成,也即socket.send(responsePacket);
    • ④:打印相关信息

  • main方法

    • 构造UDPServer对象,并绑定指定端口号,如9090,也即UDPServer server = new UDPServer(9090)
    • 启动服务端,也即server.start()

对于客户端(UDPClient类):

  • 构造方法(public UDPClient(String serverIP, int serverPort)

    • 需要建立一个DatagramSocket,但不指定端口号,也即DatagramSocket socket =new DatagramSocket()。客户端无需绑定端口号是因为客户端上运行状况复杂,端口号占用情况各不相同,无法保证所指定的端口号在数据报来临时一定是空闲的,所以这里让系统自动指定空闲端口号即可

    • 需要建立一个InetSocketAddress,传入服务端serverIPserverPort,也即SocketAddress ADDRESS = new InetSocketAddress(serverIP, serverPort),这里的serverPort就是服务端中所指定的那个port。之所以这样做是因为客户端发送时必须要知道服务端的IP地址和port

      • InetSocketAddressSocketAddress的子类
  • 客户端处理逻辑(public void start()

    • ①:读取客户端中用户的输入

      • 使用Scanner接受即可,也即String request = scanner.next()
    • ②:发送请求给服务端

      • 需要构造一个DatagramPacket给服务端发送数据报,注意需要将类型Stringrequest转化为byte[],同时传入服务端的ADDRESS。也即DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length, ADDRESS);
      • 发送行为由socket完成,也即socket.send(requestPacket)
    • ③:从服务端获取响应

      • 需要构造一个DatagramPacket用于接受服务端端发来的数据报,会保存在byte[]中,也即DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096)
      • 接受行为由socket完成,也即socket.receive(responsePacket)
      • 接受到的responsePacket 其类型为byte[],所以需要把它转为String以便于查看,也即String response = new String(responsePacket.getData(), 0, resoibsePacket.getLength())
    • ④:打印相关信息

  • main方法

    • 构造UDPClient对象,并给定服务端IPport,也即 UDPClient client = new UDPClient("127.0.0.1", 9090)
    • 启动客户端端,也即client.start()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/147197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s之ConfigMap和secret

写在前面 我们知道k8s的数据都是存储到kv数据库etcd中的,那么我们程序中使用到各种配置信息是否可以也存储到etcd,然后在pod中使用呢?是可以的,k8s为了实现将自定义的数据存储到etcd,定义了ConfigMap 和secret两种API…

《后端技术面试 38 讲》学习笔记 Day 01

《后端技术面试 38 讲》学习笔记 Day 01 学习目标 在2022年春节将至(半个月),适合在这个冬天里,温故知新。通过学习一门覆盖面较广的课程,来夯实基础,完善自己的知识体系,是一个很棒的选择。 …

LCHub:未来,低代码产品矩阵是500强企业的绝佳选择

近日,国内知名咨询机LCHub发布2022《中国大型企业数字化升级路径研究》。 报告认为由于大型企业的数字化需求旺盛、购买力充足,因此国内成熟的数字化服务商普遍以大型企业为核心客户。大型企业与数字化服务商的供需磨合决定了我国数字化市场的形态,造就了我国数字化市场与海…

go map 源码逐行阅读

map粗略介绍 源码开头注释: A map is just a hash table. The data is arranged into an array of buckets. Each bucket contains up to 8 key/elem pairs. The low-order bits of the hash are used to select a bucket. Each bucket contains a few high-order…

Linux学习笔记——RabbitMQ安装部署

5.4、RabbitMQ安装部署 5.4.1、简介 RabbitMQ是一款知名的开源消息列队系统,为企业提供消息的发布、订阅、点对点传输等消息服务。 RabbitMQ在企业开发中十分常见,课程为大家演示快速搭建RabbitMQ环境。 5.4.2、安装 RabbitMQ在yum仓库中的版本比较老…

用于从单细胞FRET数据中提取灵敏度分布的Matlab代码

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 对于分子生物学来讲,生物分析手段的发展,是阐明机理的必要条件。在研究分子间相互作用的道路上&#xf…

Leetcode - 106 - 相交链表

160. 相交链表 题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意&am…

【阶段三】Python机器学习04篇:机器学习项目实战:多元线性回归模型、岭回归模型与套索回归模型

本篇的思维导图: 一元线性回归的数学原理 一元线性回归模型又称为简单线性回归模型,其形式可以表示为如下所示的公式。 y=ax+b 其中,y为因变量,x为自变量,a为回归系数,b为截距。 如下图所示,其中y(i)为实际值,y(i)为预测值,一元线性回归的目的就是拟合出一…

Vision-Only Robot Navigation in a Neural Radiance World

Paper name Vision-Only Robot Navigation in a Neural Radiance World Paper Reading Note URL: https://arxiv.org/abs/2110.00168 TL;DR RA-L 2022 文章,提出在 NeRF 表达的环境中进行机器人导航及循迹任务的方法 Introduction 背景 基于 on-board 传感器…

HTML与CSS基础(五)—— CSS布局(盒子模型)、PxCook使用

目标能够认识 盒子模型 的组成部分 能够掌握盒子模型的 边框、内边距、外边距 的作用及简写形式能够计算盒子的 实际大小 能够了解 外边距折叠现象,并知道如何解决 盒子塌陷问题一、PxCook的基本使用1. 通过软件打开设计图① 打开软件 ② 拖拽入设计图 ③ 新建项目2…

Acwing---99.激光炸弹

激光炸弹1.题目2.基本思想3.代码实现1.题目 地图上有 NNN 个目标,用整数 Xi,YiXi,YiXi,Yi 表示目标在地图上的位置,每个目标都有一个价值 WiWiWi。 注意:不同目标可能在同一位置。 现在有一种新型的激光炸弹,可以摧毁一个包含 …

Java中常用API总结(4)—— Object类(含实例解读和源码阅读)

Object类一、前言二、概述1.API帮助文档2.使用方法三、常用方法1.toString方法1️⃣格式2️⃣实例3️⃣源码阅读4️⃣快捷键重写方法2.equals方法1️⃣格式2️⃣实例3️⃣源码阅读4️⃣重写方法3.对象克隆四、结语一、前言 本文将讲述有关于Object类相关知识点 二、概述 1.A…

C语言文件操作的细节

目录 文本文件和二进制文件 概念 一个数据在内存中是怎么存储的呢? 通过VS2013可以查看二进制数值 文件读取结束的判定 文件缓冲区 文本文件和二进制文件 概念 根据数据的组织形式,数据文件被称为文本文件或者二进制文件。 数据在内存中以二进制的…

YOLOv5 以txt 或json格式输出预测结果

YOLOv5 以txt 或json格式输出预测结果1.YOLOv5源码以多种格式输出预测结果1.run函数——传入参数2.run函数——保存打印2.YOLOv5以.txt格式输出预测结果1.执行以下代码就可以得到以.txt格式输出预测结果2.输出格式:3.YOLOv5以.json格式输出预测结果1.需要在源码中加…

零售行业交易数据分析(3)——群组/同期群分析(留存率分析)

内容简介 本文介绍了群组分析(同期群分析)的方法以及Python实现过程,并继续对一家零售公司的交易数据进行用户留存分析和可视化。 本系列的文章: 《零售行业交易数据分析(1)——客户终身价值(CLTV)计算和…

Qt扫盲-QSplitter理论总结

QSplitter理论总结一、概述二、使用说明1. 添加子控件2. 内部控件大小和位置一、概述 QSplitter允许用户通过拖动子部件之间的边界来控制子部件的大小。这个经常在我们使用的一些工具软件中最常使用 比如就像 QAssistant 里面的索引栏和内容直间,鼠标放在那个分界区…

3dMax中的两足动物及动画制作方法

3dMax的两足动物简介 3DMax是一款专业的3D电脑设计软件,用于制作3D动画、游戏、模型、图像等,在视频游戏开发商、影视工作室的工作中发挥着重要作用。Biped 是3D max 软件中动画的基本部分。3dMax中的Biped为角色建模中的角色部分提供运动并将其连接到现…

基于Java+SpringMvc+vue+element实现驾校管理系统详细设计

基于JavaSpringMvcvueelement实现驾校管理系统详细设计 博主介绍:5年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

PPI网络的构建与美化(String+Cytoscape)

目录写在前面一、使用string分析数据二、使用Cytoscape构建网络1. 导入TSV文件2. Analyze Network3. Generate Style4. CytoNCA计算Betweenness三、美化网络1. 根据Betweenness调整网络2. 选择你需要的蛋白,做个双环网络图3. 调整字体大小颜色、气泡大小等4. 保存图…

【TypeScript】JavaScript VS TypeScript数据类型

💭💭 ✨:JavaScript VS TypeScript数据类型   💟:东非不开森的主页   💜: 你若盛开,清风自来💜💜   🌸: 如有错误或不足之处,希望可以指正&…