Udp网络编程
基于Tcp协议的网络通信能够建立可靠的连接,同时也将消耗大量的系统性能,为了减少系统开销,在网络通信中提供了UDP传输协议。UDP是不可靠的连接,广泛应用于个中聊天工具中。
使用UDP协议发送数据,所有的信息以数据报的形式发送,但客户端不一定能够接受成功。在Java中使用DatagramSocket类和DatagramPacket类实现Udp网络通信。
一:DatagramSocket
方法 | 类型 | 描述 |
---|---|---|
public DatagramSocket() | 构造方法 | 构造DatagramSocket对象不指定监听端口 |
public DatagramSocket(int prot) | 构造方法 | 构造DatagramSocket对象指定监听端口 |
public void send(DatagramPacket p) | 构造方法 | 发送数据报 |
public void receive(DatagramPacket p) | 方法 | 接受数据报 |
使用DatagramSocket类编写发送程序,在构造DatagramSocket对象时若未指定端口号,系统将自动分配一个端口号。这就相当于店电话时,可以使用固话、小灵通、手机实现拨号。但对方的电话号码是固定的,即接收程序必须指定一个端口号。
UDP
数据报通过数据报套接字
DatagramSocket
发送和接收,
系统不保证
UDP
数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
二:DatagramPacket
方法 | 类型 | 描述 |
public DatagramPacket(byte[] buf,int length) | 构造方法 | 构造DatagramPacket对象时指定内存空间和大小 |
public DatagramPacket(byte[] buf,int length,InetAddress address,int prot) | 构造方法 | 构造DatagramPacket对象时指定内存空间和大小、目标地址和端口 |
public byte[] getData() | 方法 | 返回接收数据 |
public int getLength() | 方法 | 返回发送或接收数据的长度 |
public InetAddress getAddress() | 方法 | 返回机器的地址 |
DatagramPacket
对象封装了
UDP
数据报,在数据报中包含了发送端的
IP
地址和端口号以及接收端的
IP
地址和端口号。
UDP
协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
三:InetAddress类
方法 | 类型 | 描述 |
---|---|---|
public static InetAddressgetByName(String host) | 方法 | 通过主机名或Ip地址获得一个InetAddtess |
public static String getHostName() | 方法 | 获取Ip地址对应的主机名 |
public String getHostAddress() | 方法 | 返回IP地址字符串 |
InetAddress类用于表示计算机地址。
udp通信流程
流程:
1.
DatagramSocket与DatagramPacket
2.
建立发送端和接收端
3.
建立数据包
4.调用
Socket的发送、接收方法
5.
关闭Socket
编写UDP网络程序需要分别编写发送程序和接收程序。他们是两个独立的运行程序。
例一:
注意:先开接收端。(不想多说)
/**
* 发送程序
* @throws IOException
*/
@org.junit.Test
public void send() throws IOException{
//创建一个数据报
DatagramSocket ds=new DatagramSocket();
byte[] buf="hello world".getBytes();
//创建一个数据包,每一个数据包不能大于64k,发送数据信息(buf)发送到(哪?)IP(127.0.0.1)、端口号,(9090)
DatagramPacket dp=new DatagramPacket(buf, 0, buf.length, InetAddress.getByName("127.0.0.1"),9090);
ds.send(dp);
ds.close();
}
/**
* 接收程序
* @throws IOException
*/
@org.junit.Test
public void receive() throws IOException{
DatagramSocket ds=new DatagramSocket(9090);
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf, 0, buf.length);
//把数据报中的数据写入到 dp中数据包中
ds.receive(dp);
System.out.println(new String(dp.getData(),0,dp.getLength()));
ds.close();
}
打印结果:hello world
例二:
/**
* 发送程序
*/
@org.junit.Test
public void UdpSend(){
DatagramSocket ds=null;
DatagramPacket dp=null;
try {
//ds用于完成消息的发送
ds=new DatagramSocket();
String info="hello world";
/**
* 将待发的消息包装为DatagramPacket,DatagramPacket指定了消息放松的目标主机地址及端口
*/
dp=new DatagramPacket(info.getBytes(), info.getBytes().length,InetAddress.getByName("localhost"),3000);
ds.send(dp);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
ds.close();//消息发送完毕后,关闭对象
}
}
/**
* 接收程序
*/
@org.junit.Test
public void UdpReceive(){
DatagramSocket ds=null;
DatagramPacket dp=null;
byte[] buf=new byte[1024];
try {
/**
* (发送程序)发送信息时,指定消息发送的目标端口是3000,所以在接收程序中,要构建
* DatagramSocket对象时,端口号应与发送程序数据包中指定的端口号一致
*/
ds=new DatagramSocket(3000);//拿到3000端口的数据报
dp=new DatagramPacket(buf, 1024);//创建一个数据包,接收发送程序传递的数据。
ds.receive(dp);//把从3000端口的数据报信息写入(接收)到dp数据包中。
String str=new String(dp.getData(),0,dp.getLength());
str=str+" from "+dp.getAddress().getHostAddress();
System.err.println(str);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
ds.close();
}
}
接收端打印结果:hello world from 127.0.0.1