## Java编程那些事儿105——网络编程技术4
陈跃峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
### 13.2.4 UDP编程
网络通讯的方式除了TCP方式以外,还有一种实现的方式就是UDP方式。UDP(User Datagram Protocol),中文意思是用户数据报协议,方式类似于发短信息,是一种物美价廉的通讯方式,使用该种方式无需建立专用的虚拟连接,由于无需建立专用的连接,所以对于服务器的压力要比TCP小很多,所以也是一种常见的网络编程方式。但是使用该种方式最大的不足是传输不可靠,当然也不是说经常丢失,就像大家发短信息一样,理论上存在收不到的可能,这种可能性可能是1%,反正比较小,但是由于这种可能的存在,所以平时我们都觉得重要的事情还是打个电话吧(类似TCP方式),一般的事情才发短信息(类似UDP方式)。网络编程中也是这样,必须要求可靠传输的信息一般使用TCP方式实现,一般的数据才使用UDP方式实现。
UDP方式的网络编程也在Java语言中获得了良好的支持,由于其在传输数据的过程中不需要建立专用的连接等特点,所以在Java API中设计的实现结构和TCP方式不太一样。当然,需要使用的类还是包含在java.net包中。
在Java API中,实现UDP方式的编程,包含客户端网络编程和服务器端网络编程,主要由两个类实现,分别是:
1. DatagramSocket
DatagramSocket类实现“网络连接”,包括客户端网络连接和服务器端网络连接。虽然UDP方式的网络通讯不需要建立专用的网络连接,但是毕竟还是需要发送和接收数据,DatagramSocket实现的就是发送数据时的发射器,以及接收数据时的监听器的角色。类比于TCP中的网络连接,该类既可以用于实现客户端连接,也可以用于实现服务器端连接。
2. DatagramPacket
DatagramPacket类实现对于网络中传输的数据封装,也就是说,该类的对象代表网络中交换的数据。在UDP方式的网络编程中,无论是需要发送的数据还是需要接收的数据,都必须被处理成DatagramPacket类型的对象,该对象中包含发送到的地址、发送到的端口号以及发送的内容等。其实DatagramPacket类的作用类似于现实中的信件,在信件中包含信件发送到的地址以及接收人,还有发送的内容等,邮局只需要按照地址传递即可。在接收数据时,接收到的数据也必须被处理成DatagramPacket类型的对象,在该对象中包含发送方的地址、端口号等信息,也包含数据的内容。和TCP方式的网络传输相比,IO编程在UDP方式的网络编程中变得不是必须的内容,结构也要比TCP方式的网络编程简单一些。
下面介绍一下UDP方式的网络编程中,客户端和服务器端的实现步骤,以及通过基础的示例演示UDP方式的网络编程在Java语言中的实现方式。
UDP方式的网络编程,编程的步骤和TCP方式类似,只是使用的类和方法存在比较大的区别,下面首先介绍一下UDP方式的网络编程客户端实现过程。
UDP客户端编程涉及的步骤也是4个部分:建立连接、发送数据、接收数据和关闭连接。
首先介绍UDP方式的网络编程中建立连接的实现。其中UDP方式的建立连接和TCP方式不同,只需要建立一个连接对象即可,不需要指定服务器的IP和端口号码。实现的代码为:
DatagramSocket ds = new DatagramSocket();
这样就建立了一个客户端连接,该客户端连接使用系统随机分配的一个本地计算机的未用端口号。在该连接中,不指定服务器端的IP和端口,所以UDP方式的网络连接更像一个发射器,而不是一个具体的连接。
当然,可以通过制定连接使用的端口号来创建客户端连接。
DatagramSocket ds = new DatagramSocket(5000);
这样就是使用本地计算机的5000号端口建立了一个连接。一般在建立客户端连接时没有必要指定端口号码。
接着,介绍一下UDP客户端编程中发送数据的实现。在UDP方式的网络编程中,IO技术不是必须的,在发送数据时,需要将需要发送的数据内容首先转换为byte数组,然后将数据内容、服务器IP和服务器端口号一起构造成一个DatagramPacket类型的对象,这样数据的准备就完成了,发送时调用网络连接对象中的send方法发送该对象即可。例如将字符串“Hello”发送到IP是127.0.0.1,端口号是10001的服务器,则实现发送数据的代码如下:
~~~
String s = “Hello”;
String host = “127.0.0.1”;
int port = 10001;
//将发送的内容转换为byte数组
byte[] b = s.getBytes();
//将服务器IP转换为InetAddress对象
InetAddress server = InetAddress.getByName(host);
//构造发送的数据包对象
DatagramPacket sendDp = new DatagramPacket(b,b.length,server,port);
//发送数据
ds.send(sendDp);
~~~
在该示例代码中,不管发送的数据内容是什么,都需要转换为byte数组,然后将服务器端的IP地址构造成InetAddress类型的对象,在准备完成以后,将这些信息构造成一个DatagramPacket类型的对象,在UDP编程中,发送的数据内容、服务器端的IP和端口号,都包含在DatagramPacket对象中。在准备完成以后,调用连接对象ds的send方法把DatagramPacket对象发送出去即可。
按照UDP协议的约定,在进行数据传输时,系统只是尽全力传输数据,但是并不保证数据一定被正确传输,如果数据在传输过程中丢失,那就丢失了。
UDP方式在进行网络通讯时,也遵循“请求-响应”模型,在发送数据完成以后,就可以接收服务器端的反馈数据了。
下面介绍一下UDP客户端编程中接收数据的实现。当数据发送出去以后,就可以接收服务器端的反馈信息了。接收数据在Java语言中的实现是这样的:首先构造一个数据缓冲数组,该数组用于存储接收的服务器端反馈数据,该数组的长度必须大于或等于服务器端反馈的实际有效数据的长度。然后以该缓冲数组为基础构造一个DatagramPacket数据包对象,最后调用连接对象的receive方法接收数据即可。接收到的服务器端反馈数据存储在DatagramPacket类型的对象内部。实现接收数据以及显示服务器端反馈内容的示例代码如下:
~~~
//构造缓冲数组
byte[] data = new byte[1024];
//构造数据包对象
DatagramPacket received = new DatagramPacket(data,data.length);
//接收数据
ds.receive(receiveDp);
//输出数据内容
byte[] b = receiveDp.getData(); //获得缓冲数组
int len = receiveDp.getLength(); //获得有效数据长度
String s = new String(b,0,len);
System.out.println(s);
~~~
在该代码中,首先构造缓冲数组data,这里设置的长度1024是预估的接收到的数据长度,要求该长度必须大于或等于接收到的数据长度,然后以该缓冲数组为基础,构造数据包对象,使用连接对象ds的receive方法接收反馈数据,由于在Java语言中,除String以外的其它对象都是按照地址传递,所以在receive方法内部可以改变数据包对象receiveDp的内容,这里的receiveDp的功能和返回值类似。数据接收到以后,只需要从数据包对象中读取出来就可以了,使用DatagramPacket对象中的getData方法可以获得数据包对象的缓冲区数组,但是缓冲区数组的长度一般大于有效数据的长度,换句话说,也就是缓冲区数组中只有一部分数据是反馈数据,所以需要使用DatagramPacket对象中的getLength方法获得有效数据的长度,则有效数据就是缓冲数组中的前有效数据长度个内容,这些才是真正的服务器端反馈的数据的内容。
UDP方式客户端网络编程的最后一个步骤就是关闭连接。虽然UDP方式不建立专用的虚拟连接,但是连接对象还是需要占用系统资源,所以在使用完成以后必须关闭连接。关闭连接使用连接对象中的close方法即可,实现的代码如下:
ds.close();
需要说明的是,和TCP建立连接的方式不同,UDP方式的同一个网络连接对象,可以发送到达不同服务器端IP或端口的数据包,这点是TCP方式无法做到的。
介绍完了UDP方式客户端网络编程的基础知识以后,下面再来介绍一下UDP方式服务器端网络编程的基础知识。
UDP方式网络编程的服务器端实现和TCP方式的服务器端实现类似,也是服务器端监听某个端口,然后获得数据包,进行逻辑处理以后将处理以后的结果反馈给客户端,最后关闭网络连接,下面依次进行介绍。
首先UDP方式服务器端网络编程需要建立一个连接,该连接监听某个端口,实现的代码为:
DatagramSocket ds = new DatagramSocket(10010);
由于服务器端的端口需要固定,所以一般在建立服务器端连接时,都指定端口号。例如该示例代码中指定10010端口为服务器端使用的端口号,客户端端在连接服务器端时连接该端口号即可。
接着服务器端就开始接收客户端发送过来的数据,其接收的方法和客户端接收的方法一直,其中receive方法的作用类似于TCP方式中accept方法的作用,该方法也是一个阻塞方法,其作用是接收数据。
接收到客户端发送过来的数据以后,服务器端对该数据进行逻辑处理,然后将处理以后的结果再发送给客户端,在这里发送时就比客户端要麻烦一些,因为服务器端需要获得客户端的IP和客户端使用的端口号,这个都可以从接收到的数据包中获得。示例代码如下:
~~~
//获得客户端的IP
InetAddress clientIP = receiveDp.getAddress();
//获得客户端的端口号
Int clientPort = receiveDp.getPort();
~~~
使用以上代码,就可以从接收到的数据包对象receiveDp中获得客户端的IP地址和客户端的端口号,这样就可以在服务器端中将处理以后的数据构造成数据包对象,然后将处理以后的数据内容反馈给客户端了。
最后,当服务器端实现完成以后,关闭服务器端连接,实现的方式为调用连接对象的close方法,示例代码如下:
ds.close();
介绍完了UDP方式下的客户端编程和服务器端编程的基础知识以后,下面通过一个简单的示例演示UDP网络编程的基本使用。
- 前言
- (1)序言
- (2)程序设计是什么?
- (3)你适合学习程序设计吗?
- (4)如何学好程序设计?
- (5)程序设计介绍小结
- (6)计算机软件基本概念
- (7)进制的概念
- (8)计算机内部的数据表达
- (9)网络编程基础
- (10)Java语言简介
- (11)JDK的获得、安装和配置
- (12)第一个HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基础使用进阶
- (15)如何学好Java语法
- (16)代码框架、关键字和标识符
- (17)基本数据类型
- (18)变量和常量
- (19)数据类型转换
- (20)空白、语句结束和注释
- (21)算术运算符
- (22)比较运算符
- (23)逻辑运算符
- (24)赋值运算符
- (25)位运算符
- (26)移位运算符
- (27)其它运算符
- (28)运算符优先级
- (29)表达式
- (30)流程控制基础
- (31)if语句语法(1)
- (32)if语句语法(2)
- (33)if语句语法(3)
- (34)switch语句语法
- (35)while语句语法
- (36)do-while语句语法
- (37)for语句语法
- (38)break和continue语句
- (39)流程控制综合示例1
- (40)流程控制综合示例2
- (41)流程控制综合示例3
- (42)流程控制综合练习
- (43)数组概述
- (44)数组基础语法
- (45)数组使用示例1
- (46)数组使用示例2
- (47)数组使用示例3
- (48)多维数组基础
- (49)多维数组使用示例1
- (50)多维数组使用示例2
- (51)多维数组练习
- (52)方法声明
- (53)方法声明示例
- (54)方法调用
- (55)方法重载和参数传递
- (56)方法练习
- (57)面向对象基础
- (58)类(一)
- (59)类(二)
- (60)对象
- (61)面向对象设计方法和面向对象特性(一)
- (62)继承(二)
- (63)多态性
- (64)访问控制符、修饰符和其它关键字
- (65)static修饰符
- (66)final修饰符
- (67)this和super
- (68)抽象类和接口(一)
- (69)抽象类和接口(二)
- (70)抽象类和接口(三)
- (71)内部类简介
- (72)包的概念
- (73)JDK文档使用
- (74)java.lang包介绍1
- (75)String类使用
- (76)StringBuffer类和System类
- (77)包装类
- (78)时间和日期处理
- (79)Random随机处理
- (80)集合框架简述
- (81)异常处理概述
- (82)异常处理语法1
- (83)异常处理语法2
- (84)IO简介
- (85)IO类体系
- (86)文件操作之File类使用
- (87)文件操作之读取文件
- (88)文件操作之写文件
- (89)读取控制台输入
- (90)装饰流使用1
- (91)装饰流使用2
- (92)IO使用注意问题
- (93)多线程基础
- (94)多线程实现方式1
- (95)多线程实现方式2
- (96)多线程使用示例1
- (97)多线程使用示例2
- (98)多线程问题及处理1
- (99)多线程问题及处理2
- (100)多线程问题及处理3
- (101)网络编程概述
- (102)网络编程技术1
- (103)网络编程技术2
- (104)网络编程技术3
- (105)网络编程技术4
- (106)网络编程技术5
- (107)网络协议概念
- (108)网络编程示例1
- (109)网络编程示例2
- (110)网络编程小结