一、什么是UDP?
TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据。相对TCP,UDP则是面向无连接的协议。
使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。
虽然用UDP传输数据不可靠,但它的优点是和TCP比,速度快,对于不要求可靠到达的数据,就可以使用UDP协议。
二、JAVA相关API
2.1 DatagramSocket: (创建Socket)
DatagramSocket创建例子(20000是绑定的端口):
DatagramSocket ds = new DatagramSocket(20000);
2.2 DatagramPacket: (把要发送或接收的数据都封装到DatagramPacket中,然后由DatagramSocket发送或接收)
getAddress():获得DatagramPacket中的IP地址。
getPort():获得DatagramPacket中的I端口号。
DatagramPacket其实就是构建一个包,包里面有内容,有目标的IP,目标的端口号。
接收数据代码:
byte[] buf = new byte[512]; //接收数据的缓冲区
DatagramPacket receivePack = new DatagramPacket(buf, buf.length);//包装
ds.receive(receivePack); //通过DatagramSocket的receive方法把数据写进receivePack中
发送和接收的代码:
//接收缓存
final byte[] buf = new byte[512];
DatagramPacket receivePack = new DatagramPacket(buf,buf.length);
//接收来自发送方的数据data
ds.receive(receivePack);
//构建回送数据
String responeData = "Receive data with len:"+dataLen;
byte[] responseDataBytes = responeData.getBytes();
DatagramPacket responsePacket = new DatagramPacket(responseDataBytes,
responseDataBytes.length,receivePack.getAddress(),receivePack.getPort());
ds.send(responsePacket);
三、UDP通信例子:
3.1 局域网搜索
步骤:
1.主机B(提供方)监听本机的20000端口。
2. A电脑(搜索方,搜索局域网内监听20000端口的主机) 向 局域网内的 计算机的20000端口发送消息。(假设A的发送端口是10000)
3. 这时候B电脑会收到A电脑的消息(B收到消息后,就可以确认A的端口了),如果A电脑监听本机的10000端口,如果B往10000端口发送数据,A也会收到B的消息。
4. 这样就实现了信息的交互。
下面这个代码是提供方的代码,会等待一次发送方的数据并接收,如果没有发送方发送数据,会阻塞。
提供方:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPProvider {
public static void main(String[] args) throws IOException {
System.out.println("UDPProvider started");
//绑定20000端口
DatagramSocket ds = new DatagramSocket(20000);
//接收信息的实体
final byte[] buf = new byte[512];
DatagramPacket receivePack = new DatagramPacket(buf,buf.length);
//监听绑定的端口并准备接收(下面这条语句会阻塞,一定等待有发送方来发数据为止)
ds.receive(receivePack);
//打印发送者的信息
String ip = receivePack.getAddress().getHostAddress();//发送方IP
int port = receivePack.getPort(); //发送方的端口
int dataLen = receivePack.getLength(); //数据长度
String data = new String(receivePack.getData(),0,dataLen);
System.out.println("receive from IP:"+ip+" port:"+port
+"\t"+"data:"+data);
//构建回送数据
String responeData = "Receive data with len:"+dataLen;
byte[] responseDataBytes = responeData.getBytes();
DatagramPacket responsePacket = new DatagramPacket(responseDataBytes,
responseDataBytes.length,receivePack.getAddress(),receivePack.getPort());
ds.send(responsePacket);
ds.close();
}
}
搜索方:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSeacher {
public static void main(String[] args) throws IOException {
System.out.println("UDPSeacher started");
//搜索方负责发送数据,因此本机的发送端口可以让系统随机分配,不人为指定
DatagramSocket ds = new DatagramSocket();
//构建发送数据
String requestData = "Hello world";
byte[] requestDataBytes = requestData.getBytes();//以当前系统默认的编码转称对应的字节序。
//直接构建packet
DatagramPacket requestPacket = new DatagramPacket(requestDataBytes,
requestDataBytes.length);
//设置发送报文的信息,如本机IP,目标端口20000
requestPacket.setAddress(InetAddress.getLocalHost());
//往对方主机的20000端口发送数据
requestPacket.setPort(20000);
ds.send(requestPacket);
//接收信息的实体
final byte[] buf = new byte[512];
DatagramPacket receivePack = new DatagramPacket(buf,buf.length);
//接收
ds.receive(receivePack);
//发送者的IP
String ip = receivePack.getAddress().getHostAddress();
int port = receivePack.getPort();
int dataLen = receivePack.getLength();
String data = new String(receivePack.getData(),0,dataLen);
System.out.println("UDPSeacher receive from IP:"+ip+" port:"+port
+"\t"+"data:"+data);
ds.close();
}
}
先运行提供方,再运行搜索方,因为提供方是监听的,没有监听,你发信息没人能收。
效果:
提供方:
从下面结果看来,提供方收到了搜索方法来的data:hello world。并且可以知道,搜索方的端口号是61877(这是随机的分配的,但提供方监听的端口号则是人为固定的)
搜索方:
结合提供方的代码可知,提供方收到搜索方法来的数据后,是会恢复一个数据给搜索方的。从搜索方的结果看来,确实是收到了提供方的回复数据,端口是20000,没错,因为提供方的端口就是20000。