UDP 简介

UDP(User Datagram Protocol,用户数据报协议)是传输层的另一种协议,比 TCP 具有更快的传输速度,但是不可靠。UDP 发送的数据单元被称为 UDP 数据报,当网络传输 UDP 数据报时,无法保证数据报一定到达目的地,也无法保证各个数据报按发送的顺序到达目的地,例如:当发送方先发送包含字符串【hello】的数据报,再发送包含字符串【everyone】的数据报时,接收方有可能先接收到字符串【everyone】,再接收到字符串【hello】,也有可能什么数据也没有接收到,因为发送方发送的数据有可能在传输途中都被丢失了

DatagramPacket 类

DatagramPacket 表示数据报,它的构造方法可以被分为两种:

  • 创建用来接收数据的 DatagramPacket 对象
  • 创建用来发送数据的 DatagramPacket 对象

两种构造方法的主要区别是:

  • 用于发送数据的构造方法需要设定数据报到达的目的地的地址
  • 用于接收数据的构造方法无须设定地址

用于接收数据的构造方法包括:

//data:用来存放接收到的数据
//length:指定要接收的字节数
//offset:指定在data存放数据的起始位置,即data[offset],如果没有设定,那么初始位置为data[0]
public DatagramPacket(byte[] data, int length);
public DatagramPacket(bytel data, int offset, int length);

用于发送数据的构造方法包括:

//data:用来存放要发送的数据
//length:指定要发送的字节数
//offset:指定在data要发送数据的起始位置,即data[offset],如果没有设定,那么初始位置为data[0]
//address和port:来指定目的地的地址
public DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int offset, int length, SocketAddress address);
public DatagramPacket(byte[] data, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int length, SocketAddress address);

DatagramPacket 类包括以下属性,提供了一系列 get/set 方法来获取或设置这些属性:

  • data:表示数据报的数据缓冲区
  • offset:表示数据报的数据缓冲区的起始位置
  • length: 表示数据报的长度
  • address:对于用于发送的数据报,address 属性表示数据报的目标地址。对于用于接收的数据报,address 属性表示发送者的地址
  • port:对于用于发送的数据报,port 属性表示数据报的目标 UDP 端口。对于用于接收的数据报,port 属性表示发送者的 UDP 端口

DatagramSocket 类

DatagramSocket 类负责接收和发送数据报,每个 DatagramSocket 对象都会与一个本地端口绑定,在此端口监听发送过来的数据报。在客户程序中,一般由操作系统为 DatagramSocket 类分配本地端口,这种端口也被称为匿名端口。在服务器程序中,一般由程序显式地为 DatagramSocket 类指定本地端口

DatagramSocket 的构造方法有以下几种重载形式:

//由操作系统分配的任意的可用端口
DatagramSocket();
//显式指定本地端口
DatagramSocket(int port);
//同时指定IP和端口
DatagramSocket(int port, InetAddress laddr);
DatagramSocket(SocketAddress bindaddr);

DatagramSocket 的 send 方法负责发送一个数据报,该方法的定义如下:

public void send(DatagramPacket dp) throws IOException

值得注意的是,UDP 提供不可靠的传输,如果数据报没有到达目的地,那么 send 方法不会抛出任何异常,发送方程序就无法知道数据报是否被接收方接收到,除非双方通过应用层的特定协议来确保接收方未收到数据报时,发送方能重发数据报

DatagramSocket 的 receive 方法负责接收一个数据报,该方法的定义如下:

public void receive(DatagramPacket datagramPacket) throws IOException

此方法从网络上接收一个数据报,如果网络上没有数据报,执行该方法的线程就会进入阻塞状态,直到收到数据报为止。参数 datagramPacket 用来存放接收到的数据报,如果接收的数据报太大,receive 方法会在 datagramPacket 的数据缓冲区内存放尽可能多的数据,其余的数据则丢弃

两个 TCP Socket 之间存在固定的连接关系,而一个 DatagramSocket 可以与其他任意一个 DatagramSocket 交换数据报。在某些场合,一个 DatagramSocket 可能只希望与固定的另一个远程 DatagramSocket 通信,从 JDK1.2 开始,DatagramSocket 添加了一些方法,利用这些方法,可以使一个 DatagramSocket 只能与另一个固定的 DatagramSocket 交换数据报

//该方法实际上不建立TCP意义上的连接,但能限制当前DataramSocket只对参数指定的远程主机和UDP端口收发数据报
public void connect(InetAddress host, int port);
//中止当前DatagramSocket已经建立的连接
public void disconnect();
//当且仅当DatagramSocket已经建立连接时返回所连接的远程UDP端口,否则返回“-1”
public int getPort();
//当且仅当DatagramSocket已经建立连接时返回所连接的远程主机的IP地址,否则返回null
public InetAddress getlnetAddress();
//当且仅当DatagramSocket已经建立连接时返回所连接的SocketAddress,否则返回null
public SocketAddress getRemoteSocketAddress();

DatagramSocket 的 close 方法会释放所占用的本地 UDP 端口,在程序中及时关闭不再需要的 DatagramSocket,这是好的编程习惯

DatagramChannel 类

DatagramChannel 是 SelectableChannel 的子类,可以被注册到一个 Selector。使用 DatagramChannel,可以使 UDP 服务器只需用单个线程就能同时与多个客户通信。DatagramChannel 在默认情况下采用阻塞模式,如果希望该为非阻塞模式,那么可以调用 configureBlocking(false) 方法

DatagramChannel 类的静态 open 方法返回一个 DatagramChannel 对象,每个 DatagramChannel 对象都关联了一个 DatagramSocket 对象,DatagramChannel 对象的 socket 方法返回这个 DatagramSocket 对象

DatagramChannel 对象被创建后,与它关联的 DatagramSocket 对象还没有被绑定到任何地址,必须调用 DatagramSocket 对象的 bind 方法来与一个本地地址绑定

DatagramChannel channel = DatagramChannel.open();
DataqramSocket socket = channel.socket();
SocketAddress address = new InetSocketAddress(8000);
socket.bind(address);

与 DatagramSocket 一样,DatagramChannel 的 connect(SocketAddress remote) 方法使得通道只能对特定的远程地址收发数据报

DatagramChannel 使用 send 方法发送数据

//把参数src的剩余数据作为一个数据报写到通道中,参数target指定目标地址,该方法返回发送的字节数
public int send(ByteBuffer src, SocketAddress target) throws IOException

DatagramChannel 使用 receive 方法从通道中读取一个数据报,存放在参数指定的 ByteBufer,并返回数据报的发送方的地址

public SocketAddress receive(ByteBuffer dst) throws IOException

如果 DatagramChannel 工作于阻塞模式,那么 receive 方法在读取到数据报之前不会返回。如果 DatagramChannel 工作于非阻寒模式,那么 receive 方法在没有数据报可读取的情况下立即返回 null

DatagramChannel 也可以使用 write 方法发送数据,与 send 方法区别在于:write 方法要求 DatagramChannel 已经建立连接

public int write(ByteBuffer src) throws IOException;
//依次发送ByteBuffer数组中每个ByteBuffer的数据
public long write(ByteBufferl] srcs) throws IOException;
//参数offse指定ByteBuffer数组的起始位置参数,length指定发送的ByteBuffer的数目
public long write(ByteBufferl] srcs, int offset, int length) throws IOException;

DatagramChannel 也可以使用 read 方法接收数据,同样的,它也要求 DatagramChannel 已经建立连接

public int read(ByteBuffer src) throws IOException;
//把数据报的数据保存到 ByteBuffer 数组中
public long read(ByteBuffer[l srcs) throws IOException;
public long read(ByteBuffer[] srcs, int offset, int length) throws IOException;

Java 网络编程 —— 基于 UDP 的数据报和套接字的更多相关文章

  1. 【Java】Java网络编程菜鸟进阶:TCP和套接字入门

    Java网络编程菜鸟进阶:TCP和套接字入门 JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protoco ...

  2. java网络编程(二)可中断套接字

    参考资料:java核心技术 卷II 为中断套接字操作,可使用java.nio包提供的SocketChannel类.可以使用如下方式打开SocketChannel: SocketChannel chan ...

  3. Java 网络编程 --基于UDP实现一对一聊天功能

    UDP 基本流程: UDP发送端基本流程: 1.使用DatagramSocket 指定端口 创建发送端 2.准备数据 一定转成字节数组 3. 封装成DatagramPacket 包裹,需要指定目的地 ...

  4. Java 网络编程 -- 基于TCP 模拟多用户登录

    Java TCP的基本操作参考前一篇:Java 网络编程 – 基于TCP实现文件上传 实现多用户操作之前先实现以下单用户操作,假设目前有一个用户: 账号:zs 密码:123 服务端: public c ...

  5. java网络编程--4 UDP

    java网络编程--4 UDP 1.7.UDP 发短信:不用连接,但是需要知道对方的地址 主要包含两个类:DatagramPacket 和 DatagramSocket 发送消息 发送端: packa ...

  6. Learning-Python【30】:基于UDP协议通信的套接字

    UDP协议没有粘包问题,但是缓冲区大小要足够装数据包大小,建议不要超过 512 服务端: # 服务端 import socket server = socket.socket(socket.AF_IN ...

  7. Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)

    IPv4套接字地址结构 struct sockaddr_in { uint8_t sinlen;(4个字节) sa_family_t sin_family;(4个字节) in_port_t sin_p ...

  8. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

  9. java 网络编程基础 UDP协议的Socket:DatagramSocket;广播Socket:MulticastSocket

    什么是UDP协议: UDP协议是一种不可靠的网络协议,它在通信实例的两端各建立一个Socket 但这两个 Socket之间并没有虚拟链路,这两个Socket只是发送.接收数据报的对象.Java 提供了 ...

  10. java Socket编程-基于UDP

    package com.wzy.UDPTest; import java.net.DatagramPacket; import java.net.DatagramSocket; import java ...

随机推荐

  1. JUC并发编程学习(十三)ForkJoin

    ForkJoin 什么是ForkJoin ForkJoin在JDK1.7,并发执行任务!大数据量时提高效率. 大数据:Map Reduce(把大任务拆分成小任务) ForkJoin特点:工作窃取 为什 ...

  2. 模拟ASP.NET Core MVC设计与实现

    前几天有人在我的<ASP.NET Core框架揭秘>读者群跟我留言说:"我最近在看ASP.NET Core MVC的源代码,发现整个系统太复杂,涉及的东西太多,完全找不到方向,你 ...

  3. CatCatCat

    拿到题目没有思路,查看了题解 附件 放到kali中用string找flag,得到一个密钥,可以用来下面的解密 打开我养了-- 发现里面以U2F开头,结合txt名称"我养了一只叫兔子的91岁的 ...

  4. L2-034 口罩发放

    重点在阅读理解能力 身份证号必须是18位数字,话说平时咱们身份证也可以带个X啥的啊. 合法状态就是只要身份证合格就行,一开始我还想是它犯病,然后申请了口罩才算一个合法记录. 后边输出状态为1的人,一定 ...

  5. (Good topic)卡牌分组(3.27leetcode每日打卡)

    给定一副牌,每张牌上都写着一个整数. 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:  每组都有 X 张牌. 组内所有的牌上都写着相同的整数. 仅当你可选的 X &g ...

  6. JavaWeb项目练习(学生选课管理系统)三【登录功能】

    需求: 首页为用户登录页面,管理员,教师,学生三种角色用户登录后,进入相应的功能页. 在index.jsp文件里跳转到login.jsp页面,为了更好地书写 <%@ page contentTy ...

  7. 🔥🔥Java开发者的Python快速实战指南:实用工具之PDF转DOCX文档(可视化界面)

    首先,大家对Python语法的了解已经基本完成,现在我们需要开始进行各种练习.我为大家准备了一些练习题目,比如之前的向量数据库等,这些题目可以参考第三方的SDK来进行操作,文档也是比较完善的.这个过程 ...

  8. 玩转 K8s 权限控制:RBAC + kubeconfig 搞定 kubectl 权限管理那些事

    1. 先抛需求 当一个 K8s 集群需要被多个租户共享时,就涉及到了权限问题,比如你是管理员,这时候你会面临着"给每个用户分配一个 Namespace"类似的需求. 更进一步,可能 ...

  9. linux云服务器病毒处理

    阿里云服务器被挖矿病毒入侵,CPU跑满,需要先停止相关进程.为了根除病毒,还需要 解决系统的后门问题(这部分听从阿里云工程师的建议备份系统盘快照后重置系统,再通过快照恢复数据) 然而重置系统后依然存在 ...

  10. vulnhub - Nagini - writeup

    信息收集 基础信息 目标只开放了22和88: root@Lockly tmp/nagini » arp-scan -I eth1 -l Interface: eth1, type: EN10MB, M ...