Java网络编程——基于UDP的数据报和套接字

java.net.ServerSocket与java.net.Socket建立在TCP的基础上。TCP是网络传输层的一种可靠的数据传输协议。如果数据在传输途中被丢失或损坏,那么TCP会保证再次发送数据;如果数据到达接收方的顺序被打乱,那么TCP会在接收方重新恢复数据的正确顺序。应用层无须担心接收到乱序或错误的数据,应用层只需从Socket中获得输入流和输出流,就可以方便地接收和发送数据。当发送方先发送字符串“hello”,再发送字符串“everyone”时,接收方在应用层必定先接收到字符串“hello”,再接收到字符串“everyone”。接收方不会先接收到字符串“everyone”,再接收到字符串“hello”。

TCP的可靠性是有代价的,这种代价就是传输速度的降低。建立和销毁TCP连接会花费很长的时间。如果通信双方实际上通信的时间很短,要传输的数据很少,那么建立和销毁TCP连接的代价就相对较高。

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

1、UDP简介

如果应用层关心数据能否正确到达,那么就应该在传输层使用TCP。例如应用层的FTP和HTTP都建立在TCP的基础上。如果应用层仅关心发送的数据能否快速到达目的地,则可以考虑在传输层使用UDP。例如,用UDP传输实时音频时,如果丢失了数据报或打乱数据报的顺序,则只会导致接收方出现噪音,而适量的噪音是可以容忍的。但是如果用TCP传输实时音频,则由于速度很慢,会导致接收方常常出现停顿,声音时断时续,这是无法容忍的。由此可见,UDP比TCP更适于传输实时音频。

由于UDP传输数据是不可靠的,假如应用层要求接收到正确的数据,那么应用层自身必须保证数据传输的可靠性。应用层的网络文件系统(Network File System,NFS)协议,以及简单文件传输协议(Trivial FTP,TFTP)协议都建立在UDP的基础上。NFS协议和TFTP会保证可靠性,这意味着实现NFS协议或TFTP的应用程序必须处理丢失或乱序的数据报。

建立在UDP上的应用层如何保证数据传输的可靠性呢?这可以用邮局发送邮包来做解释,邮局就相当于UDP的实现者,它提供不可靠的传输。发送者通过邮局先后发送3个邮包,邮包上写明了接收者的地址,邮局把邮包发送给接收者,但是有可能部分邮包在途中被丢失,也有可能邮包到达目的地的先后顺序与发送的先后顺序不一样。发送者与接收者必须事先商量好确保接收者正确接收到邮包的协议。发送者会在邮包上标上序号,接收者收到邮包后就能按照序号排序。接收者会告诉发送者已经收到了哪些邮包,发送者就能重发那些接收者未收到的邮包。发送者与接收者使用的这种协议就相当于应用层的协议。

在Java中,java.net.DatagramSocket负责接收和发送UDP数据报,java.net.DatagramPacket表示UDP数据报。如下图所示,每个DatagramSocket都与一个本地地址(包括本地主机的IP地址和本地UDP端口)绑定,每个DatagramSocket都可以把UDP数据报发送给任意一个远程DatagramSocket,也都可以接收来自任意一个远程DatagramSocket的UDP数据报。在UDP数据报中包含了目的地址的信息,DatagramSocket根据该信息把数据报发送到目的地。
在这里插入图片描述
采用TCP通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有与客户连接的Socket,客户端的Socket与服务器端的Socket是一一对应的,它们构成了两个端点之间的虚拟的通信线路。

而UDP是无连接的协议,客户端的DatagramSocket与服务器端的DatagramSocket不存在一一对应关系,两者无须建立连接,就能交换数据报。DatagramSocket提供了接收和发送数据报的方法。

  • public void receive(DatagramPacket dst)throws IOException //接收数据报
  • public void send(DatagramPacket src)throws IOException //发送数据报

下面的EchoServer与例EchoClient就利用DatagramSocket来发送和接收数据报。在这里插入图片描述

在这里插入图片描述
在同一时刻,可能会有多个EchoClient进程与EchoServer进程通信。EchoServer的DatagramSocket与UDP端口8000绑定,EchoClient则与任意一个可用的UDP端口绑定。EchoServer在一个while循环中不断接收EchoClient的数据报,然后给EchoClient回复一个数据报。

EchoClient从控制台读取用户输入的字符串,把它包装成一个数据报,然后把它发送给EchoServer,接着再接收EchoServer的响应数据报。

值得注意的是,EchoClient与EchoServer之间的通信是不可靠的,EchoClient以及EchoServer发送的数据报有可能丢失,或者各个数据报到达目的地的顺序与发送数据报的顺序不一致。

2、DatagramPacket类

DatagramPacket表示数据报,它的构造方法可以被分为两种:一种构造方法创建的DatagramPacket对象用来接收数据,还有一种构造方法创建的DatagramPacket对象用来发送数据。两种构造方法的主要区别是,用于发送数据的构造方法需要设定数据报到达的目的地的地址,而用于接收数据的构造方法无须设定地址。

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

  • public DatagramPacket(byte[] data,int length)
  • public DatagramPacket(byte[] data,int offset,int length)

以上data参数被用来存放接收到的数据,参数length指定要接收的字节数,参数offset指定在data中存放数据的起始位置,即data[offset]。如果没有设定参数offset,那么起始位置为data[0]。参数length必须小于或等于data.length-offset,否则会抛出IllegalArgumentException。

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

  • 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)

以上data参数中存放了要发送的数据,参数length指定要发送的字节数,参数offset指定要发送的数据在data中的起始位置,即data[offset]。如果没有设定参数offset,那么起始位置为data[0]。参数length必须小于或等于data.length-offset,否则会抛出IllegalArgumentException。参数address和参数port用来指定目的地的地址。以下两段程序代码都创建了一个数据报,它的送达地址为主机“myhost”的UDP端口100。
在这里插入图片描述

3、DatagramSocket类

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

3.1、构造DatagramSocket

DatagramSocket的构造方法有以下几种重载形式:
在这里插入图片描述
第1个不带参数的构造方法使DatagramSocket对象与匿名端口绑定(即由操作系统分配的任意的可用端口),其余的构造方法都会显式地指定本地端口。第3和第4个构造方法需要同时指定IP地址和端口,这适用于一个主机有多个IP地址的场合,这两个构造方法能明确指定DatagramSocket对象所绑定的IP地址。

如果想知道一个DatagramSocket对象所绑定的本地地址,那么可以调用它的以下方法:

  • int getLocalPort():返回DatagramSocket所绑定的端口。
  • InetAddress getLocalAddress():返回DatagramSocket所绑定的IP地址。
  • SocketAddress getLocalSocketAddress():返回一个SocketAddress对象,它包含DatagramSocket所绑定的IP地址和端口信息。

3.2、接收和发送数据报

DatagramSocket的send()方法负责发送一个数据报,该方法的定义如下:
在这里插入图片描述
值得注意的是,UDP提供不可靠的传输,如果数据报没有到达目的地,那么send()方法不会抛出任何异常,发送方程序就无法知道数据报是否被接收方接收到,除非双方通过应用层的特定协议来确保接收方未收到数据报时,发送方能重发数据报。

send()方法可能会抛出IOException,但是与java.uti.Socket相比,DatagramSocket的send()方法抛出IOException的可能性很小。如果发送的数据报超过了底层网络所支持的数据报的大小,就可能会抛出SocketException,它是IOException的子类。
在这里插入图片描述
DatagramSocket的receive()方法负责接收一个数据报,该方法的定义如下:
在这里插入图片描述
此方法从网络上接收一个数据报。如果网络上没有数据报,执行该方法的线程就会进入阻塞状态,直到收到数据报为止。

参数datagramPacket用来存放接收到的数据报,datagramPacket的数据缓冲区应当足够大,以存放接收到的数据。否则,如果接收的数据报太大,receive()方法就会在datagramPacket的数据缓冲区内存放尽可能多的数据,其余的数据则被丢失。

如果接收数据时出现问题,receive()方法就会抛出IOException,但这种情况实际上极少出现。

3.3、管理连接

两个TCP Socket之间存在固定的连接关系,而一个DatagramSocket可以与其他任意一个DatagramSocket交换数据报。

在某些场合,一个DatagramSocket可能只希望与固定的另一个远程DatagramSocket通信。例如,NFS客户只接收来自与之通信的服务器的数据报。再例如,在网络游戏中,一个游戏玩家只接收他的游戏搭档的数据报。

从JDK1.2开始,DatagramSocket添加了一些方法,利用这些方法,可以使一个DatagramSocket只能与另一个固定的DatagramSocket交换数据报:

  • (1)public void connect(InetAddress host,int port):connect()方法实际上不建立TCP意义上的连接,但它能限制当前DatagramSocket只对参数指定的远程主机和UDP端口收发数据报。如果当前DatagramSocket试图对其他的主机或UDP端口发送数据报,send()方法就会抛出IllegalArgumentException。从参数以外的其他主机或UDP端口发送过来的数据报则被丢弃,程序不会得到任何通知,也不会抛出任何异常。
  • (2)public void disconnect():disconnect()中止当前DatagramSocket已经建立的“连接”,这样,DatagramSocket就可以再次对任何其他主机和UDP端口收发数据报。
  • (3)public int getPort()当且仅当DatagramSocket已经建立连接时,getPort()方法才返回DatagramSocket所连接的远程UDP端口,否则返回“-1”。
  • (4)public InetAddress getInetAddress()当且仅当DatagramSocket已经建立连接时,getInetAddress()方法才返回DatagramSocket所连接的远程主机的IP地址,否则返回null。
  • (5)public SocketAddress getRemoteSocketAddress()当且仅当DatagramSocket已经建立连接时,getRemoteSocketAddress()方法才返回一个SocketAddress对象,表示DatagramSocket所连接的远程主机以及端口的地址,否则返回null。

UDP客户程序通常只和特定的UDP服务器通信,因此可在UDP客户程序中把DatagramSocket与远程服务器连接。UDP服务器需要与多个UDP客户程序通信,因此在UDP服务器中一般不用对DatagramSocket建立特定的连接。

3.4、关闭DatagramSocket

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

3.5、DatagramSocket的选项

DatagramSocket有以下选项:

  • SO_TIMEOUT:表示接收数据报时的等待超时时间。
  • SO_RCVBUF:表示接收数据的缓冲区的大小。
  • SO_SNDBUF:表示发送数据的缓冲区的大小。
  • SO_REUSEADDR:表示是否允许重用DatagramSocket所绑定的本地地址。
  • SO_BROADCAST:表示是否允许对网络广播地址发送广播数据报。

3.6、IP服务类型选项

UDP与TCP都建立在IP基础之上,DatagramSocket也提供了设置和读取IP服务类型的方法:

  • 设置服务类型:public void setTrafficClass(int trafficClass) throws SocketException
  • 读取服务类型:public int getTrafficClass() throws SocketException

4、DatagramChannel类

从JDK1.4开始,添加了一个支持按照非阻塞方式发送和接收数据报的DatagramChannel。DatagramChannel是SelectableChannel的子类,可以被注册到一个Selector。使用DatagramChannel,可以使得UDP服务器只需用单个线程就能同时与多个客户通信。DatagramChannel在默认情况下采用阻塞模式,如果希望该为非阻塞模式,那么可以调用configureBlocking(false)方法。

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

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

相关文章

扬声器(喇叭)

扬声器(喇叭) 电子元器件百科 文章目录 扬声器(喇叭)前言一、扬声器(喇叭)是什么二、扬声器(喇叭)的类别三、扬声器(喇叭)的应用场景四、扬声器(喇叭)的作用原理总结前言 扬声器广泛应用于音响系统、公共广播系统、汽车音响、电视、电脑和移动设备等各种电子设备…

Linux基本开发工具

编译器和自动化构建工具 一、编译器——gcc、g1. 安装 gcc/g2. 使用3. 链接库4. 拓展命令:od/file/ldd/readelf 二、自动化构建项目——make、makefile1. 介绍2. 使用例子touch——change file timestampsstat——display file or file system status修改时间 .PHON…

Qt 文字描边(基础篇)

项目中有时需要文字描边的功能 1.基础的绘制文字 使用drawtext处理 void MainWindow::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.setRenderHint(QPainter::SmoothPixmapTransform, true);painte…

ceph的osd盘删除操作和iscsi扩展

ceph的osd盘删除操作 拓展:osd磁盘的删除(这里以删除node1上的osd.0磁盘为例) 1, 查看osd磁盘状态 [rootnode1 ceph]# ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 0.00298 root default -3 0.00099 host node10 hdd 0.00…

【Vins轨迹】pose_graph位姿图加载EVO精度评定

1. Vins的位姿图加载功能 如果想要对slam运行后的位姿轨迹进行评定,需要将数据保存到output文件夹中。 其中pose_graph.txt含有的信息:关键帧id、时间戳、vio的xyz、优化后的xyz、vio的四元数、优化后的四元数、回环到的关键帧id、回环信息&#xff08…

【十】python复合模式

10.1 复合模式简介 在前面的栏目中我们了解了各种设计模式。正如我们所看到的,设计模式可分为三大类:结构型、创建型和行为型设计模式。同时,我们还给出了每种类型的相应示例。然而,在软件实现中,模式并是不孤立地工作的。对于所…

HPM5300系列--第一篇 命令行开发调试环境搭建

一、目的 在之前的博客中《HPM6750系列--第二篇 搭建Ubuntu开发环境》、 《HPM6750系列--第三篇 搭建MACOS编译和调试环境》我们介绍了HPM6750evkmini开发环境的搭建过程,由于HPM5300系列共用一套hpm-sdk,故HPM5300的开发调试环境的搭建过程基本和之前的…

智能故障诊断期刊推荐【中文期刊】

控制与决策 http://kzyjc.alljournals.cn/kzyjc/home 兵工学报 http://www.co-journal.com/CN/1000-1093/home.shtml 计算机集成制造系统 http://jsjjc.soripan.net/ 机械工程学报 http://www.cjmenet.com.cn/CN/0577-6686/home.shtml 太阳能学报 https://www.tynxb.org.c…

Visual Studio Code中的任务配置文件tasks.json中的可选任务组tasks详解

☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython 一、引言 vscode是支持通过配置可以实现类似Visual C等IDE开发工具使用菜单和快捷键直接进行程序编译构建的,这样构建的任务可以结合后续的调试配置进行IDE环境的程序调试,不过在之前…

12. IO

1.File类 • File 类代表与平台无关的文件和目录。 • File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。 1).File的常用方法 在这里插入图片描述 2).遍历给定目录所有文件 …

MySQL增删改查

查询数据 MySQL 数据库使用 SQL SELECT 语句来查询数据。以下为在 MySQL 数据库中查询数据通用的 SELECT 语法: SELECT column_name,column_name FROM table_name [WHERE Clause] [LIMIT N][ OFFSET M] 查询语句中你可以使用一个或者多个表,表之间使用…

联想笔记本如何安装Vmware ESXi

环境: Vmware ESXi 8.0 Vmware ESXi 6.7 联想E14笔记本 问题描述: 联想笔记本如何安装Vmware ESXi 解决方案: 1.官网下载镜像文件 https://customerconnect.vmware.com/en/downloads/search?queryesxi%208 下载 2.没有账户注册一个 …

什么时候使用匿名类,匿名类解决了什么问题?为什么需要匿名类 ?

匿名类通常在以下场景下使用: 一次性使用: 当你需要创建一个类的实例,但该类只在一个地方使用,而不打算在其他地方重复使用时,可以考虑使用匿名类。 简化代码: 当创建一个小型的、一次性的类会让代码更简洁…

浅析特征增强个性化在CTR预估中的经典方法和效果对比

在CTR预估中,主流都采用特征embeddingMLP的方式,其中特征非常关键。然而对于相同的特征,在不同的样本中,表征是相同的,这种方式输入到下游模型,会限制模型的表达能力。为了解决这个问题,CTR预估…

【每日一题】用邮票贴满网格图

文章目录 Tag题目来源题目解读解题思路方法一:二维前缀和二维差分 写在最后 Tag 【二维前缀和】【二维差分】【矩阵】【2023-12-14】 题目来源 2132. 用邮票贴满网格图 题目解读 在 01 矩阵中,判断是否可以用给定尺寸的邮票将所有 0 位置都覆盖住&…

智能优化算法应用:基于黄金正弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于黄金正弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于黄金正弦算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黄金正弦算法4.实验参数设定5.算法结果6.…

GeoTrust OV证书

当谈到网站安全性和可信度时,GeoTrust OV证书是一个备受推崇的选择。作为一家备受尊敬的数字证书颁发机构,GeoTrust以其卓越的品牌声誉和高质量的产品而闻名于世。GeoTrust OV证书提供了一系列的安全功能,同时还具有出色的性价比,…

系统级基础信号知识【Linux】

目录 一,什么是信号 进程面对信号常见的三种反应概述 二,产生信号 1.终端按键产生信号 signal 2. 进程异常产生信号 核心转储 3. 系统调用函数发送信号 kill raise abort 小结: 4. 由软件条件产生 alarm 5. 硬件异常产生信号…

WEB服务器介绍

Web服务器是指驻留于因特网上某种类型计算机的程序。当Web浏览器连到服务器上并请求文件时,服务器将处理该请求并将文件发送到该浏览器上,附带的信息会告诉浏览器如何查看该文件,即文WEB服务器件类型。服务器使用HTTP进行信息交流&#xff0c…

Java之异常

一、异常是什么 程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 注意:异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行. 二、异常体系 三、异常的分类 (一)、编译时…