-
Notifications
You must be signed in to change notification settings - Fork 7
/
UDP.java
156 lines (133 loc) · 5.13 KB
/
UDP.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package template;
import android.content.Context;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
//发送者
class UDPSender {
private String IPv4;
private DatagramSocket socket;
/**
* //获取WiFi的ip
WifiInfo wifiInfo = ((WifiManager)context.getSystemService(Context.WIFI_SERVICE)).getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String IPv4 = ((ipAddress & 0xff) + "." + (ipAddress>>8 & 0xff) + "." +
(ipAddress>>16 & 0xff) + "." + (ipAddress>>24 & 0xff));
*/
public static UDPSender getInstance(Context context) throws SocketException {
// DatagramSocket socket = new DatagramSocket(port);//这么写会导致端口一直占用
DatagramSocket socket = new DatagramSocket(null);//这里设置为null,setReuseAddress才会有效
socket.setReuseAddress(true);//可复用,地址或者端口号
socket.setBroadcast(true);//允许发送广播
//socket不用绑定任何IP或端口号也能发送UDP广播,因为系统会自动分配端口
return new UDPSender(socket, "IPv4");
}
private UDPSender(DatagramSocket socket, String IPv4) {
this.IPv4 = IPv4;
this.socket = socket;
}
private int port = 1234;//对方接收的端口
public void send() {
try {
//要发送的数据
byte[] bytes = "hello".getBytes();
//广播地址255.255.255.255
byte[] broadcast = new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff};
// InetAddress.getByName(IPv4);//或者对方地址
//组装数据包
DatagramPacket dataPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByAddress(broadcast), port);
socket.send(dataPacket);//发送数据包
} catch (IOException e) {
// Log.e(TAG, "run: ", e);
} finally {
cancel();
}
}
//发送完数据要释放资源
public void cancel() {
if (null != socket) {
socket.close();
}
socket = null;
}
}
class UDPReceiver extends Thread {
private boolean cancelled = false;
private DatagramSocket socket;
private ReceiveListener listener;
/**
*
* @param port 要监听的本地端口
* @param listener 把收到的数据通过此接口传递出去
* @return
* @throws SocketException
*/
public static UDPReceiver getInstance(int port, ReceiveListener listener) throws SocketException {
// DatagramSocket socket = new DatagramSocket(port);//这么写会导致端口一直占用
DatagramSocket socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(port));//监听指定的端口,若是不指定端口,系统会自动分配端口
socket.setBroadcast(true);
socket.setSoTimeout(15);//设置超时时间
//若是不指定端口,此方法可获取系统自动分配的端口,然后通过某种方式告诉对方(如:广播包中携带此端口号)
// socket.getLocalPort();
return new UDPReceiver(socket, listener);
}
private UDPReceiver(DatagramSocket socket, ReceiveListener listener) {
this.socket = socket;
this.listener = listener;
}
//取消,释放资源
public void cancel() {
if (cancelled) return;
if (null != socket) socket.close();
socket = null;
listener = null;
cancelled = true;
}
@Override
public void run() {
try {
byte[] bytes;
DatagramPacket dataPacket;
while (!cancelled) {
bytes = new byte[1024];
dataPacket = new DatagramPacket(bytes, bytes.length);//存放数据的盒子
socket.receive(dataPacket);//接收数据包
new ParseThread(dataPacket, listener).start();//开线程去解析收到的数据,我这里简单粗暴了点
}
} catch (SocketTimeoutException e) {
//超时不用管
} catch (IOException e) {
// Log.e(TAG, "run: ", e);
} finally {
cancel();
}
}
//用线程去解析数据
static class ParseThread extends Thread {
private DatagramPacket dataPacket;
private ReceiveListener listener;
public ParseThread(DatagramPacket dataPacket, ReceiveListener listener) {
this.dataPacket = dataPacket;
this.listener = listener;
}
@Override
public void run() {
//把收到的数据转成字符串
String message = new String(dataPacket.getData(), dataPacket.getOffset(), dataPacket.getLength());
//解析message成你要的数据
//把数据传递出去
listener.receive(message);
dataPacket = null;
listener = null;
}
}
public interface ReceiveListener {
void receive(String message);
}
}