UDP简介
UDP(User Datagram Protocol)是一种非面向连接的提供不可靠的数据包式的数据传输协议。类似于快递运输,运输过程中可能出现丢失。Java中有些类是基于UDP协议来进行网络通讯的,有DatagramPacket、DatagramSocket、MulticastSocket等类
与TCP的区别
TCP是可靠连接传输协议,UDP是不可靠传输协议
- TCP在传输过程中不会出现丢失数据,一端没收到数据会重发,UDP在传输过程中可能丢失数据
- TCP是面向连接的,有三次握手四次挥手,UDP无需连接,只需指定IP和端口
- UDP传输有大小限制,每一个数据报需在64K以内
使用场景
TCP应用场景:当强调数据传输性能让位于数据传输的完整性,可控制性和可靠性
- Telnet远程登录
- Ftp文件传输
- 视频解码(tcp则不会出现跳帧,在网络不太好的情况下延时会比较大)
UDP应用场景:当强调输出性能而非完整性时,如音视频和多媒体的应用
- ping指令,用来检测网络上某台服务器是否还在提供服务
- 视频解码(udp会出现跳帧,网络不好的情况下延时非常低,强调实时)
实现流程:
udp通信流程
- 监听端口
- 独立线程监听接收
- 独立线程数据发送
代码结构:
代码实现:
主要实现:
package com.haoyang.networksdk.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UdpSdk {
private DatagramSocket datagramSocket;
private DatagramPacket sendDatagramPacket,receiveDatagramPacket;
private static UdpSdk udpSdk;
private ExecutorService executorService;
private UdpSdk() {
}
public static UdpSdk getInstance(){
if (udpSdk == null){
synchronized (UdpSdk.class){
if (udpSdk == null){
udpSdk = new UdpSdk();
}
}
}
return udpSdk;
}
private ExecutorService getExecutorService(){
if (executorService == null || executorService.isShutdown()){
executorService = Executors.newFixedThreadPool(4);
}
return executorService;
}
public void init(int port){
try {
datagramSocket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void sendUdpCommand(byte[] command, String ip, int port){
getExecutorService().submit(new SendCommandRunnable(command,ip,port));
}
public void receiveUdpCommand(UdpCallBack udpCallBack){
getExecutorService().submit(new ReceiveCommandRunnable(udpCallBack));
}
class SendCommandRunnable extends Thread{
private byte[] command;
private String ip;
private int port;
public SendCommandRunnable(byte[] command, String ip, int port) {
this.command = command;
this.ip = ip;
this.port = port;
}
@Override
public void run() {
try {
if (datagramSocket != null) {
sendDatagramPacket = new DatagramPacket(command, command.length, InetAddress.getByName(ip), port);
datagramSocket.send(sendDatagramPacket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ReceiveCommandRunnable extends Thread{
private UdpCallBack udpCallBack;
public ReceiveCommandRunnable(UdpCallBack udpCallBack) {
this.udpCallBack = udpCallBack;
}
@Override
public void run() {
while (true) {
try {
if (datagramSocket != null) {
byte[] bytes = new byte[1024];
receiveDatagramPacket = new DatagramPacket(bytes, bytes.length);
datagramSocket.receive(receiveDatagramPacket);
udpCallBack.onReceive(receiveDatagramPacket.getData());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
数据接收回调接口:
package com.haoyang.networksdk.udp;
public interface UdpCallBack {
void onReceive(byte[] bytes);
}
调用:
UdpSdk.getInstance().init(8888);
UdpSdk.getInstance().sendUdpCommand(new byte[]{1, 1, 1, 1, 1},"192.168.1.127", 8899);
UdpSdk.getInstance().receiveUdpCommand(new UdpCallBack() {
@Override
public void onReceive(byte[] bytes) {
Timber.i("udp"+bytes.toString());
}
});
测试工具:
为了测试udp服务端是否能够通信,使用sokit.exe测试
打开后切换到server,输入UDP Addr和Port启动udp,点击TCPListen启动服务,可监听客户端发送的消息,挺好的一个测试工具,推荐大家使用