Java网络编程 - UDP通信

news2024/11/17 2:39:25

文章目录

    • UDP通信
      • 快速入门
      • 一发一收
      • 多发多收
      • 广播组播

UDP通信

快速入门

UDP协议的特点:

UDP是一种无连接、不可靠传输的协议。

将数据源IP、目的地IP和端口以及数据封装成数据包,大小限制在64KB内,直接发送出去即可。

UDP协议通信首先要有DatagramPacket数据包对象:

DatagramPacket创建数据包对象构造器如下:

构造器说明
DatagramPacket(byte[] buf, int length, InetAddress address, int port)创建发送端数据包对象
buf:要发送的内容,字节数组
length:要发送内容的字节长度
address:接收端的IP地址对象
port:接收端的端口号
DatagramPacket(byte[] buf, int length)创建接收端的数据包对象
buf:用来存储接收的内容
length:能够接收内容的长度

DatagramPacket数据包对象常用方法如下:

方法说明
getLength()服务端可以获得实际接收到的字节个数
getAddress()获取发送端的ip地址
getPort()获取发送端的端口

其次要有发送端和接收端对象:

DatagramSocket创建发送端和接收端对象构造器如下:

构造器说明
DatagramSocket()创建发送端的Socket对象,系统会随机分配一个端口号。
DatagramSocket(int port)创建接收端的Socket对象并指定端口号

DatagramSocket发送数据包和接收数据包方法如下:

方法说明
send(DatagramPacket dp)发送数据包
receive(DatagramPacket p)接收数据包

一发一收

下面我们在代码中使用UDP通信, 实现客户端发送一条消息、服务端接收一条消息

客户端实现步骤:

  • 创建DatagramSocket对象(发送端对象)
  • 创建DatagramPacket对象封装需要发送的数据(数据包对象)
  • 使用DatagramSocket对象的send方法传入DatagramPacket对象
  • 释放资源
/**
    发送端
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建发送端对象, 发送端自带默认端口号, 也可以指定端口号
        DatagramSocket socket = new DatagramSocket();

        // 2. 创建一个数据包对象, 封装要发送的数据
        byte[] buffer = "我是要发送的数据".getBytes();
        /**
         参数一: 封装要发送的数据
         参数二: 要发送数据的长度
         参数三: 服务端的地址对象
         参数四: 服务端的端口号
         */
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);

        // 3. 使用发送端send方法, 用数据包发送对象
        socket.send(packet);

        // 4. 释放资源
        socket.close();
    }
}

接收端实现步骤:

  • 创建DatagramSocket对象并指定端口(接收端对象)
  • 创建DatagramPacket对象接收数据(数据包对象)
  • 使用DatagramSocket对象的receive方法传入DatagramPacket对象
  • 释放资源
package com.chenyq.d2_udp1;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
    服务端
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建接收端对象
        DatagramSocket socket = new DatagramSocket(8888);

        // 2. 创建一个数据包对象接受数据
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        // 3. 使用接收端的receive方法, 用数据包接受数据
        socket.receive(packet);

        // 4. 根据实际接受数据的字节个数获取结果
        int len = packet.getLength();
        String res = new String(buffer, 0 , len); // 将字节数据转为字符串
        System.out.println(res);

        // 5. 释放资源
        socket.close();
    }
}

测试: 先启动接收端, 再启动发送端; 可以在接收端获取到结果

多发多收

需求

  • 使用UDP通信方式开发接收端和发送端。

分析

  • 发送端可以一直发送消息。
  • 接收端可以不断的接收多个发送端的消息展示。
  • 发送端输入了exit则结束发送端程序。

客户端实现步骤:

  • 创建DatagramSocket对象(发送端对象)
  • 使用while死循环不断的接收用户的数据输入,如果用户输入的exit则退出程序
  • 如果用户输入的不是exit, 把数据封装成DatagramPacket
  • 使用DatagramSocket对象的send方法将数据包对象进行发送
  • 释放资源
/**
    发送端
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建发送端对象, 使用默认端口发送
        DatagramSocket socket = new DatagramSocket();

        // 2. 使用while死循环不断地接收用户输入数据, 如果输入exit则退出程序
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("发送消息: ");
            String inp = sc.nextLine();

            // 3. 用户输入exit则下线
            if ("exit".equals(inp)) {
                System.out.println("下线成功");
                socket.close(); // 释放资源
                break;
            }

            // 使用DatagramSocket对象的send方法将数据包对象进行发送
            byte[] buffer = inp.getBytes();
            // 创建数据包对象
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);
            socket.send(packet);
        }
    }
}

接接收端实现步骤:

  • 创建DatagramSocket对象并指定端口(接收端对象)
  • 创建DatagramPacket对象接收数据(数据包对象)
  • 使用while死循环, 不断的使用DatagramSocket对象的receive方法接收数据
/**
    接收端
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建接收端对象
        DatagramSocket socket = new DatagramSocket(8888);

        // 2. 创建数据包对象
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

      	// 3. 不断地接受数据
        while (true) {
            socket.receive(packet);
            int len = packet.getLength();
            String res = new String(buffer, 0, len);
            System.out.println("收到了来自" + packet.getAddress() + "的消息: " + res);
        }
    }
}

广播组播

UDP的三种通信方式:

单播:单台主机与单台主机之间的通信。

广播:当前主机与所在网络中的所有主机通信。

组播:当前主机与选定的一组主机的通信。

在这里插入图片描述

UDP如何实现广播:

使用广播地址:255.255.255.255

具体操作:

  • 发送端发送的数据包的目的地写的是广播地址、且指定端口。 (例如: 255.255.255.255 , 端口: 9999)
  • 本机所在同一个网段的其他主机的程序, 只要注册对应端口就可以收到消息了。(9999)
/**
    发送端
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("发送消息: ");
            String inp = sc.nextLine();

            if ("exit".equals(inp)) {
                System.out.println("下线成功");
                break;
            }

            byte[] buffer = inp.getBytes();
            // 发送的地址应该是广播地址
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
                    InetAddress.getByName("255.255.255.255"), 9999);
            socket.send(packet);
        }
    }
}
/**
 接收端
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        // 注册相同的端口号即可收取广播发送的消息
        DatagramSocket socket = new DatagramSocket(9999);

        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            socket.receive(packet);
            int len = packet.getLength();
            String res = new String(buffer, 0, len);
            System.out.println("收到了来自" + packet.getAddress() + "的消息: " + res);
        }
    }
}

UDP如何实现组播:

使用组播地址:224.0.0.0 ~ 239.255.255.255

具体操作:

  • 发送端的数据包的目的地是组播IP (例如:224.0.1.1, 端口:9999)
  • 接收端必须绑定该组播IP(224.0.1.1),端口还要注册发送端的目的端口9999 ,这样即可接收该组播消息。
  • DatagramSocket的子类MulticastSocket可以在接收端绑定组播IP。
/**
 发送端
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("发送消息: ");
            String inp = sc.nextLine();

            if ("exit".equals(inp)) {
                System.out.println("下线成功");
                break;
            }

            byte[] buffer = inp.getBytes();
            // 发送的地址使用组播地址
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
                    InetAddress.getByName("224.0.1.1"), 8888);
            socket.send(packet);
        }
    }
}
/**
 接收端
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        // 使用DatagramSocket的子类MulticastSocket可以在接收端绑定组播IP
        MulticastSocket socket = new MulticastSocket(8888);
        // 把当前接收端加入到一个组播组中去: 绑定对应的组播消息的组播IP
        socket.joinGroup(InetAddress.getByName("224.0.1.1"));

        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            socket.receive(packet);
            int len = packet.getLength();
            String res = new String(buffer, 0, len);
            System.out.println("收到了来自" + packet.getAddress() + "的消息: " + res);
        }
    }
}

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

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

相关文章

flume kafka channel 应用详解

1 官方文档 Documentation -> Flume User Guide2 kafka source (消费者) Kafka Source is an Apache Kafka consumer that reads messages from Kafka topics. If you have multiple Kafka sources running, you can configure them with the same Consumer Group so each …

2.DjangoRestFramework【基于DRF的RESTAPI的序列化使用】

进入Django rest framwork官网就能看到rest_framwork相关的教程; 1.安装rest_framwork pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support2.在setting中注册 setting…

QT-线性拟合(自动找直线区域)

最近有个需求,需要对一个S曲线的散点图做线性拟合,百度上线性拟合和曲线拟合公式很多,没什么问题,但需求里面有一个预期就是自动找出直线部分,前面因为其它事情耽搁,一直没有实现,心里多少有点梗…

SpringBoot微服务项目,转发并响应下载请求

在微服务项目中,我经常会碰到从一个微服务项目转发下载请求并实现下载文件的需求,因此在此做一个转发下载的示例。总的下载转发流程如下,我会按照这个流程一一介绍下载流程。 1、客户端的下载请求 这里主要介绍controller层是如何接收客户端…

apple pencil一代平替笔有哪些?平替电容笔推荐

当今社会,高科技推动了数字产品的发展。无论是在工作中,还是在学习中,大的屏幕都能让画面变得更清楚。不管是现在还是未来,Ipad设备都会变成我们每天的一个重要组成部分。如果ipad与一款易于使用的电容笔相结合,将会大…

git-secret:在 Git 存储库中加密和存储密钥(下)

在本篇文章中,将带你了解如何在 Docker 容器中设置git-secret和gpg,通过 Makefile recipe 为不同的场景创建工作流。 Makefile Adjustment 将git-secret和gpg指令添加到 Makefile 中.make/01-00-application-setup.mk: # File: .make/01-0…

C语言基础复习

目录 数组 一维数组 完全初始化int a[5]{1,2,3,4,5}; 不完全初始化int a[5]{1,2} 完全不初始化”,int a[5] 二维数组 完全初始化 不完全初始化 指针 变量的访问方式: 指针变量的定义: 指针变量的赋值: 指针变量的运算…

Spring-Security入门

简介 Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多,因为相比与Spring…

ChatGPT - InstructGPT 论文简读

发表于NLP会议:NeurlPS,EMNLP EMNLP: Empirical Methods in Natural Language Processing,自然语言处理中的经验方法NeurlPS: Neural Information Processing Systems,神经信息处理系统ChatGPT: Optimizing Language Models for Dialogue,优化对话的语言模型 ChatGPT:htt…

一文了解编程领域的模版

文章目录模版含义代码模版泛型模版引擎小结🍊在编程领域,模板是一种代码片段,它可以被重复使用,并允许您在保持代码的基本结构不变的情况下,根据需要调整其中的内容。模板通常在构建大型程序或开发一类相关程序时非常有…

Arthas的学习与使用

一、简介 Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时&#xff0c…

Maven知识点-反应堆

前言 在一个多模块的Maven项目中,反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身;但是对于多模块项目来说,反应堆就包含了各模块之间继承和依赖的关系&#xff0…

一篇带你MySQL入门

文章目录1. MySQL概述1.1 数据库相关概念1.2 MySQL数据库1.2.1 版本1.2.2 下载1.2.3 数据模型2. SQL2.1 SQL通用语法2.2 SQL分类2.3 DDL2.3.1 数据库操作2.3.2 表操作2.4 图形化界面工具2.4.1 安装2.4.2 使用2.5 DML2.5.1 添加数据2.5.2 修改数据2.5.3 删除数据2.6 DQL2.6.1 基…

每天一道大厂SQL题【Day04】大数据排序统计

每天一道大厂SQL题【Day04】大数据排序统计 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题&#x…

酒店管理|基于Springboot+Vue前后端分离实现酒店管理系统

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

webpack5从入门到精通

前言 webpack是什么? 摘自官网的一段话:webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每…

[oeasy]python0072_修改字体前景颜色_foreground_color_font

修改颜色 回忆上次内容 m 可以改变字体样式 0-9 之间设置的都是字体效果0 重置为默认1 变亮2 变暗3 斜体4 下划线5 慢闪6 快闪7 前景背景互换8 隐藏9 中划线 叠加效果 \33[1;3moeasy;分割 取消效果 21 取消 122 取消 223 取消 3一直到 290 是全部取消,回到默认 最…

静态链接库与动态链接库

静态链接库与动态链接库的区别 静态链接库:在项目中引用了库函数,编译时链接器会将引用的函数代码或变量,链接到可执行文件里,和可执行程序组装在一起 动态链接库:在编译阶段不参与链接,不会和可执行文件…

【Unity】流式播放远端音频:WAV格式音频篇(一)

先了解一下wav的格式: 参考1:【音频】WAV 格式详解_tyustli的博客-CSDN博客_wav文件格式详解wav 文件支持多种不同的比特率、采样率、多声道音频。WAV 文件格式是 Microsoft 的 RIFF 规范的一个子集,用于存储多媒体文件。RIFF(res…

git-secret:在 Git 存储库中加密和存储密钥(上)

目前市面上已经存在许多较为成熟的密钥管理产品,比如 HashiCorp Vault,AWS Secrets Manager 以及 GCP Secret Manager。由于这些产品需要集成和维护等服务,因此在项目中引入会增加一定成本和开销。阅读本文,将带你了解如何在 Dock…