Java 中UDP原理机制及实现方式介绍(建议阅读者阅读前了解下Java的基础知识,一方便理解)
1.基本概念介绍:
首先得简单介绍下UDP。
UDP( User Datagram Protocol )协议是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。它是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的 但是这种协议却是方便快捷的,因此很多通信工具和游戏仍然采用这种通信方式,虽然有时会出现数据丢帧的现象。
(此处可以简单的理解为某些无良快递机构,因为缺乏责任心,只负责发送至于包裹是否能顺利送达目的地毫不关心,因此会出现丢包或者延迟接收的现象)。
在Java中操纵UDP 使用位于JDK中Java.net包下的DatagramSocket和DatagramPacket类,可以非常方便地控制用户数据报文进行UDP的程序开发。
在UDP开发中使用DatagramPacket类来包装一条需要发送的信息,之后使用DatagramSocket类用于完成信息的发送操作。
一个完整的UDP网络开发程序是包含服务器端和客户端的。
关于UDP开发中的服务器和客户端的区别:
客户端与服务器端的唯一区别在于:服务器端的IP地址、端口是固定的,所以客户端可以直接将该数据报发送给服务器端,而服务器端则需要根据接收到的数据报来决定"反馈"数据报的目的地。
下面简单介绍下 DatagramSocket和DatagramPacket类的常用方法。
DatagramSocket类:创建接收和发送UDP的Socket实例
DatagramSocket(): 创建实例。通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。
DatagramSocket(int port):创建实例,并固定监听Port端口的报文。
DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文
receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。
send(DatagramPacket d):发送报文d到目的地。
setSoTimeout(int timeout):设置超时时间,单位为毫秒。
close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Sock
注意:1.在创建DatagramSocket类实例时,如果端口已经被使用,会产生一个SocketException的异常抛出,并导致程序非法终止,这个异常应该注意捕获。
DatagramPacket类:用于处理报文,将byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成byte数组。
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):从buf数组中,取出length长的数据创建数据包对象,目标是addr地址,port端口。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int
port):从buf数组中,取出offset开始的、length长的数据创建数据包对象,目标是addr地址,port端口。
DatagramPacket(byte[] buf, int offset, int length):将数据包中从offset开始、length长的数据装进buf数组。
DatagramPacket(byte[] buf, int length):将数据包中length长的数据装进buf数组。
getData():它从实例中取得报文的byte数组编码
2.实现方法:
想要实现UDP程序,建议首先从客户端编写,在客户端指定需要接收的端口和取得数据。
客户端(接收端)实现步骤
1. 建立udp的socket服务。要监听一个端口。 DatagramSocket ds = new
DatagramSocket(9001);
2. 定义一个缓冲区,将该缓冲区封装到packet包中。 byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
3. 通过socket的receive方法将数据存入数据包中。 ds.receive(dp);
4. 通过数据包dp的方法getData()、getAddress()、getPort()等方法获取包中的指定信息。
5. 关闭socket。 ds.close();
请看以下的代码以下是UDP的客户端程序:
import java.net.DatagramPacket ;
import java.net.DatagramSocket ;
public class UDPClient{
public static void main(String args[]) throws Exception{ // 所有异常抛出
DatagramSocket ds = null ; // 定义接收数据报的对象
byte[] buf = new byte[1024] ; // 开辟空间,以接收数据
DatagramPacket dp = null ; // 声明DatagramPacket对象
ds = new DatagramSocket(9000) ; // 客户端在9000端口上等待服务器发送信息
dp = new DatagramPacket(buf,1024) ; // 所有的信息使用buf保存
ds.receive(dp) ; // 接收数据
String str = new String(dp.getData(),0,dp.getLength()) + "from " +
dp.getAddress().getHostAddress() + ":" + dp.getPort() ;
System.out.println(str) ; // 输出内容
}
};
以上程序运行后,客户端程序已经打开了监听的端口,等待服务器端向客户端发送信息。
下面开始介绍服务器端(发送端)实现步骤
1. 建立udpsocket服务端点。该端点建立,系统会随机分配一个端口。如果不想随机配置,可以手动指定。 DatagramSocket ds = new
DatagramSocket(3000);
2. 将数据进行packet包的封装,必须要指定目的地地址和端口。 byte[] buf = "hi 红军".getBytes(); DatagramPacket
dp =new
DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),9000);
3. 通过socket服务的send方法将该包发出。 ds.send(dp);
4. 将socket服务关闭。主要是关闭资源。 ds.close();
下面开始编写UDP的发送 服务器程序—Udpserve
import java.net.DatagramPacket ;
import java.net.DatagramSocket ;
import java.net.InetAddress ;
public class UDPServer{
public static void main(String args[]) throws Exception{ // 所有异常抛出
DatagramSocket ds = null ; // 定义发送数据报的对象
DatagramPacket dp = null ; // 声明DatagramPacket对象
ds = new DatagramSocket(3000) ; // 服务端在3000端口上等待服务器发送信息\
String str = "hello World!!!" ;
dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("localhost"),9000) ; // 所有的信息使用buf保存
System.out.println("发送信息。") ;
ds.send(dp); // 发送信息出去
ds.close() ;
}
};
服务器端程序运行后,客户端就可以接收服务器端发送来的数据了。
以上是一个简单的收发过程。当然为了保证每个设备都可以收发,可以同时运行服务器和客户端程序。
从以上程序我们可以看出使用DatagramSocket进行网络通信时,服务器端无须也无法保存每个客户端的状态,客户端把数据报发送到服务器端后,完全有可能立即退出。但不管客户端是否退出,服务器端都无法知道客户端的状态。
当使用UDP协议时,如果想让一个客户端发送的聊天信息被转发到其他所有的客户端则比较困难,可以考虑在服务器端使用Set集合来保存所有的客户端 信息,每当接收到一个客户端的数据报之后,程序检查该数据报的源SocketAddress是否在Set集合中,如果不在就将该 SocketAddress添加到该Set集合中。这样又涉及一个问题:可能有些客户端发送一个数据报之后永久性地退出了程序,但服务器端还将该客户端的 SocketAddress保存在Set集合中……总之,这种方式需要处理的问题比较多,编程比较烦琐。
基于UDP数据传输特性,它的不可靠性也给我们在开发过程的带来了麻烦,针对此类问题,提出以下解决方案:
服务器和客户端 可以建立一套自己的校验方案(方案形式很多例如:XML,校验和等检验方式),如果数据包丢失造成数据不完整,采用补发的形式来完成,当然这个方案类似于TCP的握手连接。
在开发过程中还有很多细节,文章摘取网络上一些信息。文笔不好,还望见谅,此为普及类文章,希望能带给大家帮助。如若有发现什么问题,请及时指出方便我修改。谢谢。
张敬宇
2015.3.15于南京编辑
Java 中UDP原理机制及实现方式介绍(建议阅读者阅读前了解下Java的基础知识,一方便理解)的更多相关文章
- JAVA中单例模式的几种实现方式
1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线程安全就不会使用这种方式.但是如果不 ...
- Java中HashMap遍历的两种方式
Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...
- 夯实Java基础系列11:深入理解Java中的回调机制
目录 模块间的调用 多线程中的"回调" Java回调机制实战 实例一 : 同步调用 实例二:由浅入深 实例三:Tom做题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- 【夯实基础】- Java中的fail-fast机制
转载自:Java中的fail-fast机制 遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过普通的for删除删除符合条件 ...
- 结合实战和源码来聊聊Java中的SPI机制?
写在前面 SPI机制能够非常方便的为某个接口动态指定其实现类,在某种程度上,这也是某些框架具有高度可扩展性的基础.今天,我们就从源码级别深入探讨下Java中的SPI机制. 注:文章已收录到:https ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
随机推荐
- android--HttpURLConnection(转载)
android之HttpURLConnection 1.HttpURLConnection连接URL1)创建一个URL对象 URL url = new URL(http://www.baidu.com ...
- WEB系统开发方向
1. UI框架:要可以结合jquery+自定义服务器控件开发一套UI框架: 2.WEB报表设计器:用js开发一套可以自定义报表设计器: 3.WEB自定义表单+工作流设计器: 4.WEB打印组件: 5. ...
- linux启动黑屏或无法进入会话管理器
原因是因为更新软件时删除了/etc中的xserver配置文件,进入livecd将相关文件拷贝即可
- 配置MyEclipse+Hibernate连接Sql Server 2008出错
下文主要是讲述最近配置MyEclipse连接Sql Server 2008时遇到的一个问题,而不关注如何配置Sql Server 2008支持TCP/IP连接.Hibernate如何操作Sql Ser ...
- iOS开源项目集合一
http://www.th7.cn/Program/IOS/201308/146283.shtml
- js获取页面元素距离浏览器工作区顶端的距离
先介绍几个属性:(暂时只测了IE和firefox,实际上我工作中用到的最多的是chrome) 网页被卷起来的高度/宽度(即浏览器滚动条滚动后隐藏的页面内容高度) (javascript) ...
- O(1)检测2的幂次
class Solution { public: /* * @param n: An integer * @return: True or false */ bool checkPowerOf2(in ...
- php之面向对象(2)
注意:看这篇文章之前建议看看之前的文章,因为内容之间衔接性比较强.勿喷.. 面向对象,是一种思维模式的名字,并不是指某种特定的写法,面向对象简称oop,思路的核心在于:什么时候 什么东西 做什么. 编 ...
- FutureTask源码解读
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.ut ...
- Coursera《machine learning》--(14)数据降维
本笔记为Coursera在线课程<Machine Learning>中的数据降维章节的笔记. 十四.降维 (Dimensionality Reduction) 14.1 动机一:数据压缩 ...