前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java】21 基于 UDP 的网络编程

【Java】21 基于 UDP 的网络编程

作者头像
Demo_Null
发布2020-09-28 11:08:32
6200
发布2020-09-28 11:08:32
举报
文章被收录于专栏:Java 学习Java 学习

Java 提供了 DatagramSocket 对象作为基于 UDP 协议的 Socket,使用 DatagramPacket 代表 DatagramSocket 发送、接收的数据报。

1.1 UDP 基础

  UDP 协议是英文 User Datagram Protocol 的缩写,即用户数据报协议,主要用来支持那些需要在计算机之间传输数据的网络连接。UDP 协议从问世至今已经被使用了很多年,虽然 UDP 协议目前应用不如 TCP 协议广泛,但 UDP 协议依然是一个非常实用和可行的网络传输层协议。尤其是在一些实时性很强的应用场景中,比如网络游戏、视频会议等,UDP 协议的快速更具有独特的魅力。   UDP 协议是一种面向非连接的协议,面向非连接指的是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。至于对方是否可以接收到这些数据内容,UDP 协议无法控制,因此说 UDP 协议是一种不可靠的协议。UDP 协议适用于一次只传送少量数据、对可靠性要求不高的应用环境。与 TCP 协议一样,UDP 协议直接位于 IP 协议之上。实际上,IP 协议属于 OSI 参考模型的网络层协议,而 UDP 协议和 TCP 协议都属于传输层协议。   因为 UDP 协议是面向非连接的协议,没有建立连接的过程,因此它的通信效率很高;但也正因为如此,它的可靠性不如 TCP 协议。UDP 协议的主要作用是完成网络数据流和数据报之间的转换。在信息的发送端,UDP 协议将网络数据流封装成数据报,然后将数据报发送出去;在信息的接收端,UDP 协议将数据报转换成实际数据内容。

在这里插入图片描述
在这里插入图片描述

1.2 UDP 通信相关类

1.2.1 DatagramSocket 类

  Java 提供了 DatagramSocket 对象作为基于 UDP 协议的 Socket,但是 DatagramSocket 本身只是码头,不能维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java 使用 DatagramPacket 来代表数据报,DatagramSocket 接收和发送的数据都是通过 DatagramPacket 对象完成的。

在这里插入图片描述
在这里插入图片描述
构造方法

public DatagramSocket():创建一个 DatagramSocket 实例,并将该对象绑定到本机默认 IP 地址、本机所有可用端口中随机选择的某个端口。 public DatagramSocket(int prot):创建一个 DatagramSocket 实例,并将该对象绑定到本机默认 IP 地址、指定端口。 public DatagramSocket(int port, InetAddress laddr):创建一个 DatagramSocket 实例,并将该对象绑定到指定 IP 地址、指定端口。

常用方法

方法名

说明

void receive(DatagramPacket p)

从该 DatagramSocket 中接收数据报

void send(DatagramPacket p)

从该 DatagramSocket 对象向外发送数据报

1.2.2 DatagramPacket 类

  使用 DatagramSocket 发送数据报时,DatagramSocket 并不知道将该数据报发送到哪里,而是由 DatagramPacket 决定数据报的目的地。就像码头并不知道每个集装箱的目的地,码头只是将这些集装箱发送出去,而集装箱本身包含了该集装箱的目的地。

在这里插入图片描述
在这里插入图片描述
构造方法

public DatagramPacket(byte[] buf,int length):以一个空数组来创建 DatagramPacket 对象,该对象的作用是接收 DatagramSocket 中的数据。 public DatagramPacket(byte[] buf, int offset, int length):以一个空数组来创建 DatagramPacket 对象,并指定接收到的数据放入 buf 数组中时从 offset 开始,最多放 length 个字节。 public DatagramPacket(byte[] buf, int length, InetAddress addr, int port):以一个包含数据的数组来创建一个用于发送的 DatagramPacket 对象,创建该 DatagramPacket 对象时还指定了 IP 地址和端口,这就决定了该数据报的目的地。 public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):以一个包含数据的数组来创建一个用于发送的 DatagramPacket 对象,指定发送 buf 数组中从 offset 开始,总共 length 个字节。

常用方法

方法名

说明

InetAddress getAddress()

获取当前 IP

int getPort()

获取当前端口号

InetAddress.getLocalHost()

获取本地主机的 InetAddress

InetAddress.getByName(String host)

获取指定主机名的 InetAddress

InetAddress.getByAddress(byte[] addr)

获取指定 IP 的 InetAddress

InetAddress.getByAddress(String host, byte[] addr)

获取指定 主机名 和 IP 的 InetAddress


1.3 实现 UDP 通信

1.3.1 UDP 通信分析

发送端 ① 创建 DatagramSocket 对象(创建一个码头) ② 创建 DatagramPacket 对象并指定IP和端口号(装箱并集装箱贴目的地和接收港编号) ③ 调用 send() 方法发送(发送集装箱) ④ 释放资源(拆码头) 接收端 ① 创建 DatagramSocket 对象并指定端口号(创建一个码头并编号) ② 创建 DatagramPacket 对象,用于接收数据(拆箱) ③ 调用 receive() 方法接收(接收集装箱) ④ 释放资源(拆码头)

1.3.2 客户端

代码语言:javascript
复制
public class DemoSend {
    public static void main(String[] args) {
        DatagramSocket socket = null;
 
        try {
            // 创建 DatagramSocket
            socket = new DatagramSocket();
            // 创建数据
            byte[] sendBytes = "你好啊!".getBytes();
            // 创建 DatagramPacket
            DatagramPacket sendPacket = 
            	new DatagramPacket(sendBytes, sendBytes.length, InetAddress.getByAddress("xiaolaohu.work", 
            	new byte[] { (byte) 47, (byte) 103, 4, (byte) 205 }), 9999);
            // 发送数据
            socket.send(sendPacket);
 
            // 接受写回数据
            // 创建字节数组
            byte[] receiveBytes = new byte[1024];
            // 创建 DatagramPacket
            DatagramPacket receivePacket = new DatagramPacket(receiveBytes, receiveBytes.length);
            // 接受数据
            socket.receive(packet1);
            // 打印到控制台
            System.out.println(new String(receivePacket, 0, receiveBytes.length));
 
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
            if (socket != null) {
                socket.close();
            }
        }
    }
}

1.3.3 服务端

代码语言:javascript
复制
public class DemoReceive {
    public static void main(String[] args) {
        DatagramSocket socket = null;
        try {
            // 创建 DatagramSocket
            socket = new DatagramSocket(9999);
            // 创建字节数组
            byte[] receiveBytes = new byte[1024];
            // 创建 DatagramPacket
            DatagramPacket receivePacket = new DatagramPacket(receiveBytes, receiveBytes.length);
            // 接受数据
            socket.receive(receivePacket);
            //打印到控制台
            System.out.println(new String(receiveBytes, 0, receiveBytes.length));
 
            // 回写消息
            // 创建数据
            byte[] sendBytes = "收到了".getBytes();
            // 创建 DatagramPacket
            DatagramPacket sendPacket = 
              new DatagramPacket(sendBytes, sendBytes.length, receivePacket.getAddress(), receivePacket.getPort());
            // 发送
            socket.send(sendPacket);
 
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (socket != null) {
                socket.close();
            }
        }
    }
}

从上述代码可以看出使用 UDP 协议时,实际上并没有明显的服务端和客户端,因为两方都需要先建立一个 DatagramSocket 对象,用来接收或发送数据报,然后使用 DatagramPacket 对象作为传输数据的载体。通常固定 IP 地址、固定端口的 DatagramSocket 对象被称为服务端,因为该 DatagramSocket 可以被动接收数据。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-05-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 UDP 基础
  • 1.2 UDP 通信相关类
    • 1.2.1 DatagramSocket 类
      • 构造方法
      • 常用方法
    • 1.2.2 DatagramPacket 类
      • 构造方法
      • 常用方法
  • 1.3 实现 UDP 通信
    • 1.3.1 UDP 通信分析
      • 1.3.2 客户端
        • 1.3.3 服务端
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档