您的位置:首页 > 理论基础 > 计算机网络

黑马程序员--10.网络编程--03.【UDP协议相关类】【DatagramPacket类】【DatagramSocket类】【UDP发送端和接收端】

2013-08-27 17:24 941 查看

网络编程--3

UDP协议相关类

DatagramPacket类

DatagramSocket类

UDP发送端和接收端

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
Socket通信端点具备了,但是数据传输协议不一样的。因此每一种数据传输协议都有自己特有创建Socket通信端点方法

1.    UDP协议相关类

UDP协议相关类的综述

UDP协议是面相无连接的协议并且数据的传输形式数据报包与UDP传输协议本身相关的类就是DatagramSocket类与UDP每次传输数据形式相关的类就是DatagramPacket类

2.    java.net.DatagramPacket类

1). DatagramPacket类基础知识

(1). DatagramPacket类

[1]. DatagramPacket类所在的位置

DatagramPacket位于java.net包

[3]. DatagramPacket类的直接父类

DatagramSocket类的直接父类就是java.lang.Object类

[4]. DatagramPacket类的源码声明

public final class DatagramPacket {
//...
}


注意】DatagramPacket类是一个不可以被继承的类

[5]. DatagramSocket类的含义

此类是对UDP数据传输过程中的数据报 (Datagram) 包封装

(2). DatagramPacket类的构造方法

java.net.DatagramPacket类在构造方法涉及到的IP地址端口号指的是数据报包被发送的目的地所在主机IP地址端口号

[1]. 分析DatagramPacket构造函数的基本参数

{1}. DatagramPacket是对UDP数据传输协议数据的包装

{2}. 一般通用的数据使用的数据类型都是byte[]类型

{3}. 根据另一个规律:有数组,通常就会有指针计数器(有时候也叫总长度)。

因此,参数类型就有可能是下面的几种:

{3}1. byte buf[],
int
length

{3}2. byte buf[],
int
offset, int length

{4}. 注意到数据一定是用户指定的,而不是系统能够自行获取的。所以DatagramPacket的构造方法一定没有空参数的重载形式

{5}. 由于是Socket之间数据对传。可能需要指定发送的IP+ 该IP上某端口的App

{5}1. 如果这个数据报包用于发送,此时目标地址必须明确,而不能通过内部生成,因此这里面IP地址和端口号一定是同时出现

如果这个数据报包用于接收,则不用明确地址,因为Socket所在的本机就是目标,可以通过系统自动获得。

{5}和{3}进行结合,产生出常用的四种构造方法。

[2]. DatagramPacket四种常用的重载构造方法声明

用于UDP数据传输中的用于接收数据的数据报包对象

{1}. publicDatagramPacket(byte buf[],int length);

{2}. publicDatagramPacket(byte buf[],int offset,int
length);

用于UDP数据传输中的用于发送数据的数据报包对象

{3}. public DatagramPacket(byte buf[], int length,InetAddress address,int
port);

{4}. publicDatagramPacket(byte buf[],int offset,int
length,InetAddress address,int port);

规律】构造方法中凡是带有IP和PORT的DatagramPacket的数据报包都是用来发送的数据报包,否则都是用于接收的数据报包。

3). DatagramPacket类常用的方法

(1). DatagramPacket的JavaBean性质

[1]. DatagramPacket是一个不折不扣JavaBean类,它的方法主要分成了对私有字段的SetterGetter方法

[2]. DatagramSocket私有字段

{1}. 待发送数据对应的byte[]数组

byte[]
buf;
{2}. 待发送数据对应的byte[]数组有效部分对应的起始指针

int
offset;
{3}. 待发送数据对应的byte[]数组有效部分对应的总长度

int
length;
int
bufLength;
以我个人判断,现在两个属性的值是一样的

{3}1. 在setData(byte[] buf,int offset,int
length)中
this.length = length;this.bufLength = length;
{3}2. 在setData(byte[] buf)中

this.length = buf.length;this.bufLength
= buf.length;
{3}3. 在setLength(int length)中

this.bufLength =this.length;

{4}. 待发送数据应发送的目标主机的IP地址

InetAddress address;
{5}. 待发送数据应发送的目标主机上App的端口号

int
port;
(2). DatagramPacket的Setter和Getter方法

[1]. 获取/设置目标主机的IP地址

getAddress()/setAddress(InetAddressiaddr)

[2]. 获取/设置目标主机的App的Port端口号

getPort()/setPort(int iport)

[3]. 获取/设置待发送的数据报包中的原始数据

getData()/setData(xxx)

setData有三种重载形式

setData(byte[] buf,
int
offset, int length); setData(int offset);

setData(int length)

[4]. 获取/设置待发送的数据报包中的原始数据的有效总长度

getLength()/setLength(int length);

[5]. 获取/设置待发送的数据报包中的原始数据的有效起始位置

getOffset()/setOffset(int offset);

3.    java.net.DatagramSocket类

1). DatagramSocket类基础知识

(1). DatagramSocket类

[1]. DatagramSocket类所在的位置

DatagramSocket位于java.net包

[3]. DatagramSocket类的直接父类

DatagramSocket类的直接父类就是java.lang.Object类

[4]. DatagramSocket类的含义和作用

{1}. DatagramSocket类中的单词Datagram就是UDP中的字母D

{2}. 为UDP协议传输数据需要的Socket通信端点进行了封装

{3}. 此类表示的通信端点Socket用于发送接收UDP数据传输过程中的数据报
(Datagram) 包


【注意】DatagramSocket既可以用于发送数据,又可以用于接收数据

(2). DatagramSocket类的构造方法

[1]. DatagramSocketDatagramPacket构造方法中IPPort参数的关系

{1}. java.net.DatagramPacket类在构造方法涉及到的IP地址端口号

指的是Socket通信端点将数据报包发送到的目的地所在主机IP地址端口号

{2}.java.net.DatagramSocket类在构造方法涉及到的IP地址端口号

指的是Socket通信端点本身所在主机IP地址端口号

{3}. DatagramSocket构造中指定的是数据的源DatagramPacket构造中指定的是数据的目的地

[2]. 分析DatagramSocket构造函数的基本参数

注意】DatagramSocket仅仅负责数据的发送接收,而对数据的封装工作全部由DatagramPacket类的构造进行了封装。因此DatagramSocket仅仅负责从本机发出数据或者在本机接受数据。因此DatagramSocket的构造方法仅仅涉及本机IP端口号的传参。由于Socket本身位于本机的App上面,因此就算不指定本机的IP或者端口,系统也会根据内部的参数自动获取到本机的IP或者App对象的端口号。因此,可以有空参数的构造函数。

因此,参数类型就有可能是下面的几种:

{1}. 空参数

{2}. int port

{3}. InetAddressladdr, int port

[2]. DatagramPacket四种常用的重载构造方法声明

[3]. 空参构造函数

{1}. 构造方法原型

public DatagramSocket()
throws
SocketException;

{2}. 构造方法的说明

{2}1. [对端口的绑定]

构建了一个用于UDP通信的Socket端点并且将这个UDP通信端点Socket绑定到本地主机任意可用端口

{2}2. [对IP地址的绑定]

这个Socket将被绑定到由被系统内核选择的出来的IP地址,即通配符IP地址

[4]. 仅指定端口的构造函数

{1}. 构造方法原型

public DatagramSocket(intport)throwsSocketException;

{2}. 构造方法的说明

{2}1. [对端口的绑定]

构建了一个用于UDP通信的Socket端点并且将这个UDP通信端点Socket绑定到本地主机指定的端口port

{2}2. [对IP地址的绑定]

这个Socket将被绑定到由被系统内核选择的出来的IP地址,即通配符IP地址

[4]. 指定端口IP地址的构造函数

{1}. 构造方法原型

public DatagramSocket(int port,InetAddress laddr)throws SocketException;

{2}. 构造方法的说明

{2}1. [对端口的绑定]

构建了一个用于UDP通信的Socket端点并且将这个UDP通信端点Socket绑定到本地主机指定端口

{2}2. [对IP地址的绑定]

这个Socket将被绑定到本机指定的IP地址

[5]. [2]和[3]中两种重载方法的关系

public DatagramSocket(int port) throws SocketException {
this(port, null);
}


结论DatagramSocket(int port)是对DatagramSocket(int port,InetAddress laddr)的调用

2). DatagramSocket中负责通信的方法

(1). 发送数据报包

[1]. 方法原型

public
void
send(DatagramPacket p) throws IOException;

[2]. 输入参数

DatagramPacketp:要发送的数据报包

(2). 接收数据报包

[1]. 方法原型

public
void
receive(DatagramPacketp) throws IOException;

[2]. 输入参数

DatagramPacketp:接收发送方发送的数据,并打包成DatagramPacket对象存放在这个参数中。

[3]. receive方法是一个阻塞式方法。程序中如果调用了这个方法,并且对应的接收端Socket端点没有接收数据报包,就会一直等待不动直到这个接收

端的DatagramSocket接收到了数据报包,receive方法才会被执行完。这样整个程序就向下继续执行。



4.    UDP的发送端和接收端

使用Socket就是记住使用流程,直接走流程即可

1). UDP的发送端

需求:通过UDP传输方式,将一段文字数据发送出去

(1). UDP发送端的操作流程

[1]. 建立UDPSocket服务,即建立Socket发送端点。

[2]. 提供数据并将数据封装DatagramPacket中。

[3]. 通过UDP的Socket的发送功能将数据发送出去

[4]. 关闭Socket。

因为网络通讯最底层要走物理层,也就意味着底层的网卡资源被调用。所以关闭Socket就是在使用完底层资源之后对底层资源进行释放

(2). UDP端发送数据代码示例

import java.net.*;
/*
需求:通过UDP传输方式,将一段文字数据发送出去
思路:
1.建立UDPSocket服务,即建立端点
2.提供数据,并将其封装到数据报包中
3.通过Socket服务的发送功能,将数据报发送出去
4.关闭资源
*/
class UdpSend{
public static void main(String[] args) throws Exception{
//1.创建UDP服务。通过DatagramSocket建立
DatagramSocketds =new DatagramSocket();
//2.确定数据并封装成数据包
byte[] buf ="UDP is coming...".getBytes();
DatagramPacketdp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
//3.通过Socket服务将已有数据通过send方法发送出去
ds.send(dp);
//4.关闭资源
ds.close();
}
}


2). UDP的接收端

需求:定义一个App用于接收通过UDP协议传输过来的数据

(1). UDP接收端的操作流程

[1]. 建立UDPSocket服务,即建立Socket接收端点

[2].定义一个数据报包。因为要存储接收到通过UDP传输来的字节数据,并且接收到的数据有很多信息。如果自行提取会非常麻烦。因此直接封装成数据报包对象,调用该对象不同的方法从而获取接收到的数据报包中的信息。(直接利用DataPacket类的JavaBean的Getter方法获取各种信息)

[3]. 通过UDP接收端的Socket的receive方法将接收到的数据取出,并存入已定义好的数据报包对象中。

[4]. 关闭Socket资源。

注意】在建立UDP接收服务的时候,通常会监听一个端口

如何监听?在new DatagramSocket的时候,不能使用空参构造函数,应该使用至少含有一个端口号的构造函数:DatagramSocketds =new
DatagramSocket(10000);

这个端口就是给网络应用程序的一个数字标识。用于标识发送来的哪些数据到这个端口的应用程序进行处理。

发送端可以使用空参构造函数

(2). UDP端接收数据代码示例

import java.net.*;
class UdpRece{
public static void main(String[] args) throws Exception{
//1、创建udp Socket服务,建立端点
DatagramSocketds =new DatagramSocket(10000);
while(true){
//2、定义数据报包对象,用于接收发送过来的数据
byte[] buf =new byte[1024];
DatagramPacketdp =new DatagramPacket(buf, buf.length);
//3、通过udpSocket服务的receive方法将数据存入定义好的数据报包
ds.receive(dp);
//4、通过数据报包的方法来获取不同的方法
Stringip =dp.getAddress().getHostAddress();
Stringdata =new String(dp.getData(), 0,dp.getLength());
int port =dp.getPort();
System.out.println(ip+"::"+ data+ "::"+ port);
}

//5、关闭资源
//ds.close();
}
}


3). UDP的发送端和接收端的启动及程序运行结果

(1). 错误的启动顺序

[1].启动发送端,启动接收

[2]. 此时运行结果:

还没等接收端运行完,发送端已经运行完成。这样发送端发送的数据没有正确发送到接收端数据丢失

(2). 正确的启动顺序

[1]. 分析:启动接收端,启动发送端的可行性

由于接收端的DatagramSocket端点中含有对DatagramSocket的receive方法调用,这个方法是阻塞式的方法

{1}. 由于接收端的程序先运行,所以开始接收端没有数据报包。因此接收端的程序运行到receive方法之后,就阻塞停在那里等待有数据报包发送过来。

{2}. 此时启动发送端的程序,发送端会发送数据报包。这时候接收端就会接到这个数据报包。这样发送端的程序可以正确执行完成,并且发送的数据被接收端正确接收。因此这种方式的启动顺序是可行的。

(3). 运行结果

[1]. 先启动接收端的Socket服务,程序运行到receive方法之后,阻塞停下来等待有数据报包发送过来。



[2]. 再启动发送端的Socket服务,程序一下运行完成,同时接收端接收到发送端发送来的数据。



----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐