UDP协议是一种通信标准,它以一种“无连接”的方式定义的传输方式,使用Udp协议可以提高数据的传输速度。以“无连接”方式提供的网络服务,虽然可能会由于“无固定的传输信道”而出现误码,但如果用户更侧重传输速度,并可以容忍一定的误码率,那么,其传输数据高效性将成为一个很大的优势。以上是UDP传输的优点和缺点。
了解UDP之前,先了解一下什么是数据报文?
所谓数据报文,是UDP协议里传输数据的基本单元。
那么UDP是如何传输数据的呢?
根据UDP协议,源主机(即信息发送的主机)将会把通信数据流(比如字符串)拆分成若干个长度固定的数据单位,并在其中封装好目的地址、目标端口等信息。这些长度一致的包含目标地址、目标端口等信息的数据单位就叫“数据报文”。UDP协议是根据报文里的目标地址等信息直接发送,而不像TCP协议,先要建立通信信道。
在Java里的DatagramSocket对象里,抽象出了采用UDP协议传输数据的一般方法,而DatagramSocket对象则封装“数据报文”和“数据报文头”等属性。
UDP通信简易流程:
客户端->创建DatagramSocket->把通信数据打包,封装目标主机等信息->调用send,发送数据->结束通信
服务端->创建DatagramSocket->通过receive监听端口->打开数据报文->提供服务->返回服务结果->结束通信
首先我们创建一个简单客户端:
1:建立UDPSocket服务
2:提供数据,并封装
3:通过Socket发送功能,发送出去
4:关闭资源
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* Created by Administrator on 2016/11/18.
*/
//服务端
public class Udpreve {
public static void main(String[] args) throws Exception {
//1.创建Udp服务
DatagramSocket dss = new DatagramSocket(10000);
//2.创建接受数据包的一个空数据包
byte[] buf = new byte[1024];
DatagramPacket dpp = new DatagramPacket(buf, buf.length);
//3.接受数据包
dss.receive(dpp);//阻塞式方法
//4.解析数据包
String ip = dpp.getAddress().getHostAddress();
String st = new String(dpp.getData(), 0, dpp.getLength());
int port = dpp.getPort();
System.out.println("IP地址:" + ip + "--------" + "数据:" + st + "------" + "端口号:" + port);
//5.关闭通信
dss.close();
}
}
创建简单的服务端:
1::定义UDPSocket服务
2:定义一个数据包,用来存储接收到的字节数据。(为什么用数据包接收,因为数据包提供了更多功能,能够提取不同信息)
3:通过Socket服务的receive接收收据并放入已经定义好的数据包中
4:通过数据包功能,解析数据。
5:关闭通信
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Created by Administrator on 2016/11/18.
*/
//UDP客户端
public class Udpsend {
public static void main(String[] args) throws Exception{
//1.创建Udp Socaket服务
DatagramSocket ds=new DatagramSocket();
//2.提供数据,并封装到数据包中
BufferedReader buf= new BufferedReader(new InputStreamReader(System.in));
String line= null;
line=buf.readLine();
byte[] b=line.getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName("172.24.8.247"), 10000);
//3.通过Socket发送功能,发送出去
ds.send(dp);
//4.关闭资源
ds.close();
}
}
这样一个简单的C/S通信就写好了,运行结果如图:
切记一定要先打开服务端,用来监听端口,然后在打开客户端输入数据,进行通信。
下面这个是在这个简单的代码上运用多线程来做的一个山寨版QQ,可以两个人进行通讯。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Created by Administrator on 2016/11/19.
*/
class send implements Runnable{
DatagramSocket d;
public send(DatagramSocket d){
this.d=d;
}
public void run(){
try {
BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
String line =null;
while ((line = b.readLine()) != null) {
byte[] by=line.getBytes();
DatagramPacket dp=new DatagramPacket(by,by.length, InetAddress.getByName("169.254.172.244"),60000);
d.send(dp);
}
}catch (Exception e){
System.out.println(e);
}
}
}
class rec implements Runnable{
DatagramSocket d2;
public rec(DatagramSocket d2){
this.d2=d2;
}
public void run(){
try {
byte[] bb = new byte[1024];
DatagramPacket dd = new DatagramPacket(bb, bb.length);
while (true) {
d2.receive(dd);
String ip= d2.getInetAddress().getHostAddress();
String da =new String(dd.getData(),0,bb.length);
int port= dd.getPort();
System.out.println("ip"+ip+"port"+port+"------"+da);
}
}catch (Exception e){
System.out.println(e);
}
}
}
public class chatDemo {
public static void main(String[]args) throws Exception{
DatagramSocket sendDemo=new DatagramSocket();
DatagramSocket reDemo=new DatagramSocket(60001);
Thread s1=new Thread(new send(sendDemo));
Thread r1=new Thread(new rec(reDemo));
s1.start();
r1.start();
}
}