Java 网络编程 —— 基于 UDP 的数据报和套接字
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 的数据报和套接字的更多相关文章
- 【Java】Java网络编程菜鸟进阶:TCP和套接字入门
Java网络编程菜鸟进阶:TCP和套接字入门 JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protoco ...
- java网络编程(二)可中断套接字
参考资料:java核心技术 卷II 为中断套接字操作,可使用java.nio包提供的SocketChannel类.可以使用如下方式打开SocketChannel: SocketChannel chan ...
- Java 网络编程 --基于UDP实现一对一聊天功能
UDP 基本流程: UDP发送端基本流程: 1.使用DatagramSocket 指定端口 创建发送端 2.准备数据 一定转成字节数组 3. 封装成DatagramPacket 包裹,需要指定目的地 ...
- Java 网络编程 -- 基于TCP 模拟多用户登录
Java TCP的基本操作参考前一篇:Java 网络编程 – 基于TCP实现文件上传 实现多用户操作之前先实现以下单用户操作,假设目前有一个用户: 账号:zs 密码:123 服务端: public c ...
- java网络编程--4 UDP
java网络编程--4 UDP 1.7.UDP 发短信:不用连接,但是需要知道对方的地址 主要包含两个类:DatagramPacket 和 DatagramSocket 发送消息 发送端: packa ...
- Learning-Python【30】:基于UDP协议通信的套接字
UDP协议没有粘包问题,但是缓冲区大小要足够装数据包大小,建议不要超过 512 服务端: # 服务端 import socket server = socket.socket(socket.AF_IN ...
- Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)
IPv4套接字地址结构 struct sockaddr_in { uint8_t sinlen;(4个字节) sa_family_t sin_family;(4个字节) in_port_t sin_p ...
- JAVA基础知识之网络编程——-基于UDP协议的通信例子
UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...
- java 网络编程基础 UDP协议的Socket:DatagramSocket;广播Socket:MulticastSocket
什么是UDP协议: UDP协议是一种不可靠的网络协议,它在通信实例的两端各建立一个Socket 但这两个 Socket之间并没有虚拟链路,这两个Socket只是发送.接收数据报的对象.Java 提供了 ...
- java Socket编程-基于UDP
package com.wzy.UDPTest; import java.net.DatagramPacket; import java.net.DatagramSocket; import java ...
随机推荐
- 总结---Django部分
Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构.以及全功能的管理后台. Django内置的ORM跟框架内的其他模块耦合程 ...
- 校园社团活动管理系统(适合小白)基础javaweb前端项目实战【包含增删改查,mysql】一
校园社团活动管理系统(20分) 1.项目需求: 校园社团作为高校课外活动的重要组成部分,发展十分迅速,也受到越来越多学生的欢迎,社团规模.数量等都在日益增长,社团活动也更为多样和丰富.然而,大多数高校 ...
- 《深入理解 FFmpeg》第一章彩色插图汇总
layout: post title: "<深入理解 FFmpeg>第一章彩色插图" tags: - "FFmpeg" 这是<深入理解 FFm ...
- cocos2d-Js 各类碰撞检测
这里总结一下点.圆.矩形之间的简单碰撞检测算法(矩形不包括旋转状态) 点和圆的碰撞检测: 1.计算点和圆心的距离 2.判断点与圆心的距离是否小于圆的半径 isCollision: function(p ...
- 探索 ECMAScript 2023 中的新数组方法
前言 ECMAScript 2023 引入了一些新功能,以改进语言并使其更加强大和无缝.这个新版本带来了令人兴奋的功能和新的 JavaScript 数组方法,使使用 JavaScript 编程更加愉快 ...
- jextract的使用
写这个博客的目的:新人去看jextract的官网是看不懂的,就算看懂了也不会使用,一头雾水,我会从0开始教如何使用,如何搭配java去调用c函数. 首先我们得了解jextract是什么,官网的解释是一 ...
- SpringBoot对象拷贝
目录 概述 定义实体类 Car size carInfo 造测试数据 Spring BeanUtils Apache BeanUtils Cglib BeanCopier MapStruct 性能测试 ...
- 强!推荐一款自动化神器Autolt:不再重复工作
随着互联网不断发展,它给我们带来便利的同时,也带来了枯燥.重复.机械的重复工作.今天,我要和大家分享一款老牌实用的自动化工具:AutoIt,它能够让你告别繁琐的重复性工作,提高工作效率. 这里透露一下 ...
- 传统GIS与数字孪生结合带来的改变
传统的地理信息系统(GIS)在地理数据的收集.存储和分析方面发挥着重要作用,而数字孪生技术则通过虚拟模型的构建与真实世界进行交互和模拟.将传统GIS与数字孪生技术相结合,不仅增强了地理数据的可视化和分 ...
- zabbix 利用脚本发邮件(mail)
# 源码安装mailx tar jxvf mailx-12.3.tar.bz2 make && make install UCBINSTALL=/usr/bin/install #yu ...