JAVA网络编程之UDP

简介:

上一篇博客中使用的Socket是基于TCP协议的,这一篇为大家简单介绍一下UDP协议。
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。
UDP协议全称是用户数据报协议[1] ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

TCP与UDP的区别:
1. 基于连接与无连接;
2. 对系统资源的要求(TCP较多,UDP少);
3. UDP程序结构较简单;
4. 流模式与数据报模式 ;
5. TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

DatagramSocket

此类表示用来发送和接收数据报包的套接字。数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。
示例:DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888)); 这等价于:DatagramSocket s = new DatagramSocket(8888); 两个例子都能创建能够在 UDP 8888 端口上接收广播的 DatagramSocket。

构造方法

方法名 说明
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口
DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址
DatagramSocket(SocketAddress bindaddr) 创建数据报套接字,将其绑定到指定的本地套接字地址

方法摘要

返回值 方法名 说明
void bind(SocketAddress addr) 将此 DatagramSocket 绑定到特定的地址和端口
void close() 关闭此数据报套接字
void connect(InetAddress address, int port) 将套接字连接到此套接字的远程地址
void connect(SocketAddress addr) 将此套接字连接到远程套接字地址(IP 地址 + 端口号)
void disconnect() 断开套接字的连接
boolean getBroadcast() 检测是否启用了 SO_BROADCAST
DatagramChannel getChannel() 返回与此数据报套接字关联的唯一 DatagramChannel 对象(如果有)
InetAddress getInetAddress() 返回此套接字连接的地址
InetAddress getLocalAddress() 获取套接字绑定的本地地址
int getLocalPort() 返回此套接字绑定的本地主机上的端口号
SocketAddress getLocalSocketAddress() 返回此套接字绑定的端点的地址,如果尚未绑定则返回 null
int getPort() 返回此套接字的端口
int getReceiveBufferSize() 获取此 DatagramSocket 的 SO_RCVBUF 选项的值,该值是平台在 DatagramSocket 上输入时使用的缓冲区大小
SocketAddress getRemoteSocketAddress() 返回此套接字连接的端点的地址,如果未连接则返回 null
boolean getReuseAddress() 检测是否启用了 SO_REUSEADDR
int getSendBufferSize() 获取此 DatagramSocket 的 SO_SNDBUF 选项的值,该值是平台在 DatagramSocket 上输出时使用的缓冲区大小
int getSoTimeout() 获取 SO_TIMEOUT 的设置
int getTrafficClass() 为从此 DatagramSocket 上发送的包获取 IP 数据报头中的流量类别或服务类型
boolean isBound() 返回套接字的绑定状态
boolean isClosed() 返回是否关闭了套接字
boolean isConnected() 返回套接字的连接状态
void receive(DatagramPacket p) 从此套接字接收数据报包
void send(DatagramPacket p) 从此套接字发送数据报包
void setBroadcast(boolean on) 启用/禁用 SO_BROADCAST
static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 为应用程序设置数据报套接字实现工厂
void setReceiveBufferSize(int size) 将此 DatagramSocket 的 SO_RCVBUF 选项设置为指定的值
void setReuseAddress(boolean on) 启用/禁用 SO_REUSEADDR 套接字选项
void setSendBufferSize(int size) 将此 DatagramSocket 的 SO_SNDBUF 选项设置为指定的值
void setSoTimeout(int timeout) 启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位
void setTrafficClass(int tc) 为从此 DatagramSocket 上发送的数据报在 IP 数据报头中设置流量类别 (traffic class) 或服务类型八位组 (type-of-service octet)。

DatagramPacket

此类表示数据报包。数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

构造方法

方法名 说明
DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
DatagramPacket(byte[] buf, int offset, int length) 构造 DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号
DatagramPacket(byte[] buf, int length, SocketAddress address) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号

方法摘要

返回值 方法名 说明
InetAddress getAddress() 返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的
byte[] getData() 返回数据缓冲区
int getLength() 返回将要发送或接收到的数据的长度
int getOffset() 返回将要发送或接收到的数据的偏移量
int getPort() 返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的
SocketAddress getSocketAddress() 获取要将此包发送到的或发出此数据报的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)
void setAddress(InetAddress iaddr) 设置要将此数据报发往的那台机器的 IP 地址
void setData(byte[] buf) 为此包设置数据缓冲区
void setData(byte[] buf, int offset, int length) 为此包设置数据缓冲区
void setLength(int length) 为此包设置长度
void setPort(int iport) 设置要将此数据报发往的远程主机上的端口号
void setSocketAddress(SocketAddress address) 设置要将此数据报发往的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)

使用示例

服务端

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

/**
 * UDP服务端
 * 
 * @author jianggujin
 * 
 */
public class UDPServer
{
   public static void main(String[] args) throws IOException
   {
      DatagramSocket server = new DatagramSocket(9999);
      // 用于接收数据的缓冲数组
      byte[] recvBuf = new byte[100];
      // 实例化数据报对象
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
      // 接收消息
      server.receive(recvPacket);
      String recvStr = new String(recvPacket.getData(), 0,
            recvPacket.getLength());
      System.out.println("接收到消息:" + recvStr);
      int port = recvPacket.getPort();
      InetAddress addr = recvPacket.getAddress();
      String sendStr = "SUCCESS";
      byte[] sendBuf = sendStr.getBytes();

      // 创建回复数据报
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length,
            addr, port);
      // 发送回复
      server.send(sendPacket);
      server.close();
   }
}

客户端

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

/**
 * UDP客户端
 * 
 * @author jianggujin
 * 
 */
public class UDPClient
{
   public static void main(String[] args) throws IOException
   {
      DatagramSocket client = new DatagramSocket();

      String sendStr = "HI!";
      byte[] sendBuf = sendStr.getBytes();
      // 接收消息的主机,255.255.255.255可广播给局域网内所有主机
      InetAddress addr = InetAddress.getByName("127.0.0.1");
      DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length,
            addr, 9999);
      // 发送数据包
      client.send(sendPacket);
      // 用于接收数据的缓冲数组
      byte[] recvBuf = new byte[100];
      // 实例化数据报对象
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
      // 接收消息
      client.receive(recvPacket);
      String recvStr = new String(recvPacket.getData(), 0,
            recvPacket.getLength());
      System.out.println("收到消息:" + recvStr);
      client.close();
   }
}

运行结果
服务端:
接收到消息:HI!

客户端:
收到消息:SUCCESS

目录
相关文章
|
3月前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
94 11
|
12天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
63 23
|
26天前
|
网络协议 算法 安全
Go语言的网络编程与TCP_UDP
Go语言由Google开发,旨在简单、高效和可扩展。本文深入探讨Go语言的网络编程,涵盖TCP/UDP的基本概念、核心算法(如滑动窗口、流量控制等)、最佳实践及应用场景。通过代码示例展示了TCP和UDP的实现,并讨论了其在HTTP、DNS等协议中的应用。最后,总结了Go语言网络编程的未来发展趋势与挑战,推荐了相关工具和资源。
|
1月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
1月前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
|
4月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
85 13
|
4月前
|
监控 网络协议 网络性能优化
网络通信的核心选择:TCP与UDP协议深度解析
在网络通信领域,TCP(传输控制协议)和UDP(用户数据报协议)是两种基础且截然不同的传输层协议。它们各自的特点和适用场景对于网络工程师和开发者来说至关重要。本文将深入探讨TCP和UDP的核心区别,并分析它们在实际应用中的选择依据。
133 3
|
4月前
|
安全 Java API
深入探索Java网络编程中的HttpURLConnection:从基础到进阶
本文介绍了Java网络编程中HttpURLConnection的高级特性,包括灵活使用不同HTTP方法、处理重定向、管理Cookie、优化安全性以及处理大文件上传和下载。通过解答五个常见问题,帮助开发者提升网络编程的效率和安全性。
262 9
|
4月前
|
数据采集 Java API
java怎么设置代理ip:简单步骤,实现高效网络请求
本文介绍了在Java中设置代理IP的方法,包括使用系统属性设置HTTP和HTTPS代理、在URL连接中设置代理、设置身份验证代理,以及使用第三方库如Apache HttpClient进行更复杂的代理配置。这些方法有助于提高网络请求的安全性和灵活性。
147 0
|
8月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
235 1