物联网中UDP组播应用

2018-01-12 11:18:56来源:oschina作者:四个黑桃人点击

分享
物联网项目中UDP 组播应用
一 问题描述

在一个局域网中,设备A作为所有设备的控制中心,在这里我们称设备A为中控设备。中控设备开启一个端口服务,其他被控设备都与中控设备(设备A)建立TCP连接。中控设备通过TCP长连接进行命令下发,被控设备通过此通道进行数据上传等操作。当一个新的被控设备B需要接入系统时,首先需要知道中控的IP地址,我们可以使用UDP组播开启一个服务来告知对方自己的IP地址。


二 通讯过程

1、中控开启TCP端口的业务服务
2、中控开启UDP端口的地址通知的组播服务
3、设备B开启UDP接收服务
4、设备B发送获取中控服务的试探包
5、中控收到获取IP地址请求并回复
6、设备B接收服务处理返回包得到中控IP地址
7、设备B通过获取的IP地址与中控建立TCP连接


三 时序图

输入图片说明


四 代码实现
中控运行着一个Android系统,中控业务服务的模拟代码

中控业务服务代码片段


public class ControlServer {
public static final int CONTROL_PORT = 1855;
public ServerSocket serverSocket;
public static final ControlServer I = new ControlServer();
private ControlServer() {
}
private void init() throws IOException {
serverSocket = new ServerSocket(CONTROL_PORT);
}public void start(final Listener listener) {
new Thread("ControlServer") {
public void run() {
try {
startControlServer();
} catch (IOException e) {
e.printStackTrace();
listener.onFail(e);
}
}
}.start();
listener.onSuccess();
}private void startControlServer() throws IOException {
init();
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
Thread workThread = new Thread(new SocketHandler(socket));
workThread.start();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socket != null) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class SocketHandler implements Runnable{
private Socket socket;
public SocketHandler(Socket socket){
this.socket=socket;
}
public void run(){
InputStream inputStream = null;
try{
inputStream = socket.getInputStream();
while((inputStream.read()!=-1)){
continue;
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try{
if(socket!=null)
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}

中控IP试探服务的代码片段


public class ProbeServer {
static final String TAG = "ProbeServer";
static final String GROUP_IP = "239.239.239.73";
static final int PROBE_PORT = 10073;
private ExecutorService executorService;
private MulticastSocket mulitiSocket ;
public static ProbeServer I = new ProbeServer();
private ProbeServer(){}
private void init(){
executorService = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue(100));
}
public void start(final Listener listener){
new Thread("ProbeServer"){
public void run(){
try {
init();
startProbeService();
listener.onSuccess();
} catch (IOException e) {
listener.onFail(e);
}
}
}.start();
}
private void startProbeService() throws IOException {
InetAddress group = InetAddress.getByName(GROUP_IP);
mulitiSocket = new MulticastSocket(PROBE_PORT);
mulitiSocket.joinGroup(group);
byte[] buf = new byte[1000];
DatagramPacket recv = new DatagramPacket(buf, buf.length);
while (true) {
mulitiSocket.receive(recv);
int recvLength = recv.getLength();
byte[] recvBytes = new byte[recvLength];
System.arraycopy(buf, 0, recvBytes, 0, recvLength);
JSONObject json = null;
try {
json = JSON.parseObject(new String(recvBytes, StandardCharsets.UTF_8));
}catch (Exception e){
Log.i(TAG, "获取IP地址的组播消息格式错误...");
}
if (json!=null && json.containsKey("msgType") && json.getIntValue("msgType") == ProbeMessage.PROBE_MSG_TYPE) {
final ProbeMessage probeMessage = new ProbeMessage();
probeMessage.fromIP = recv.getAddress().getHostAddress();
probeMessage.fromPort = recv.getPort();
executorService.submit(new Runnable() {
@Override
public void run() {
String str_send = probeMessage.fromIP;
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
InetAddress loc = InetAddress.getByName(probeMessage.fromIP);
DatagramPacket dp_send = new DatagramPacket(str_send.getBytes(), str_send.length(), loc, probeMessage.fromPort+1);
ds.send(dp_send);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(ds!=null){
ds.close();
}
}
}
});
}
}
}
}
五 总结

1、在IP试探服务中使用组播相比于使用UDP广播更合适,组播地址约定更为简单,广播地址随着网段的变
化对应着也会变化
2、组播地址相比广播更为安全,在流量方面也更为合理

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台