[置顶] 基于UDP实现的android局域网视频同步播放
2016-08-19 17:58
911 查看
前段时间给公司的项目实现了一个局域网视频同步播放的功能,最近稍微空闲一些,所以稍微整理下,分享给大家学习下,文末附有下载地址。
在实现之前先科普下UDP的三种形式:“单播(Unicast)”、“多播(Multicast)”和“广播(Broadcast)”。
单播:好比一个人对另外一个人说话,此时信息的接收和传递 只在两个节点之间进行 。
广播:主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接收到所有信
息(不管你是否需要),由于其不用路径选择,所以其网络成本可以很低廉。
组播:主机之间”一对一组”的通讯模式,也就是加入了同一个组的主机可以接受到此组内的所有数据,网络中的交换机和路由器只向
有需求者复制并转发其所需数据。
以下以分别以UDP的 广播 和组播形式实现局域网的同步播放。
广播和多播使用的都是D类IP地址,D类IP地址第一个字节以“lll0”开始,它是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。
所以我们可以通过广播或者组播形式来告诉局域网其他设备当前播放的情况从而实现视频同步播放。
先来讲解下整体实现思路:定义一个While(true)的线程去监测UDP请求,当收到主机发来数据包后我们对数据包进行截取,获取到有效信信息后发送广播出去做行进相应的处理.
我们所关心的是通过udp通信我们得到的是什么数据,所以在这里我们定义了2组指令数据包:
(1) “11#autosyncplay#” + AutoSyncGroup + “#” + System.currentTimeMillis() + “#” + final_asi + “#” + 同步路径
(2) “22#autosyncplay#” + AutoSyncGroup + “#” + index + “#” + position;
第一串指令是用来发起同步用的,第二组指令是用来通知进度改变的。11是标示发起同步用的,22是标示同步进度的,以#来分割信息,获取数据时候按#来分割获取。
所以在获取到数据之后我们就从中提取出我们需要的的信息进行处理,以下为处理数据部分代码:
它不被路由发送,但会被送到相同物理网络段上的所有主机IP地址的网络字段和主机字段
全为1就是地址255.255.255.255(假如路由器将此类地址数据转发出去全世界都能收到
你发出的消息想想都恐怖)
2)直接广播
网络广播会被路由,并会发送到专门网络上的每台主机IP地址的网络字段定义这个网络,
主机字段通常全为1,如 192.168.10.255 .
前面已经说了需要一台设备作为Server发出自己的进度,其他设备作为Client接收到数据后做相应的
处理所以有一个Server发出数据包,和多个Clinet接收相应的数据。
1.Server发起同步
因为不知道大家的路由网关地址,所以就以255这个受限地址作为目标地址,方便大家导入查看效果。
2.Clinet接收数据包
1.Server发起同步
需要注意的是组播需要路由器支持,有的路由并没有严格按照的UPnP协议来实现所以会出现自己能收到消息别人收不到, 或者自己收不到别人也收不到等情况。
2.Clinet接收组播数据包
源码下载,点击这里
github地址:https://github.com/mythace/Udp_LAN_SysPlay 欢迎satr or fork .
一.概述
实现局域网视频同步播放,首先需要这些设备都有相同的文件,大家同时去播放相同的文件就可以了。所以我们选定一台设备作为主机,将自己当前播放的视频文件 以及进度告诉给其他设备,其他设备收到消息后去播放这个视频,并且seek到指定的进度位置。在实现之前先科普下UDP的三种形式:“单播(Unicast)”、“多播(Multicast)”和“广播(Broadcast)”。
单播:好比一个人对另外一个人说话,此时信息的接收和传递 只在两个节点之间进行 。
广播:主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接收到所有信
息(不管你是否需要),由于其不用路径选择,所以其网络成本可以很低廉。
组播:主机之间”一对一组”的通讯模式,也就是加入了同一个组的主机可以接受到此组内的所有数据,网络中的交换机和路由器只向
有需求者复制并转发其所需数据。
以下以分别以UDP的 广播 和组播形式实现局域网的同步播放。
广播和多播使用的都是D类IP地址,D类IP地址第一个字节以“lll0”开始,它是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。
所以我们可以通过广播或者组播形式来告诉局域网其他设备当前播放的情况从而实现视频同步播放。
先来讲解下整体实现思路:定义一个While(true)的线程去监测UDP请求,当收到主机发来数据包后我们对数据包进行截取,获取到有效信信息后发送广播出去做行进相应的处理.
我们所关心的是通过udp通信我们得到的是什么数据,所以在这里我们定义了2组指令数据包:
(1) “11#autosyncplay#” + AutoSyncGroup + “#” + System.currentTimeMillis() + “#” + final_asi + “#” + 同步路径
(2) “22#autosyncplay#” + AutoSyncGroup + “#” + index + “#” + position;
第一串指令是用来发起同步用的,第二组指令是用来通知进度改变的。11是标示发起同步用的,22是标示同步进度的,以#来分割信息,获取数据时候按#来分割获取。
所以在获取到数据之后我们就从中提取出我们需要的的信息进行处理,以下为处理数据部分代码:
private void doDealData(String data, String AutoSyncGroup,String type) { if (data.startsWith("11#autosyncplay#" + AutoSyncGroup + "#")) { //开启同步指令 String[] darr = data.split("#"); String asi = ""; if (darr.length >= 5) asi = darr[4]; String dir = ""; if (darr.length >= 6) dir = darr[5]; AppDebug.Log(tag, type+"...AutoSyncGroup=" + AutoSyncGroup + ",asi=" + asi); Intent intent = new Intent(); intent.setAction(MainService.ACT_SYNC_RELOAD_PAGE); intent.putExtra("AutoSyncInterval", asi); intent.putExtra("dir", dir); MainService.getAppContext().sendBroadcast(intent); } else if (data.startsWith("22#autosyncplay#" + AutoSyncGroup + "#")) { //同步进度指令 String[] darr = data.split("#"); int fileindex = 0; if (darr.length >= 4) fileindex = Integer.parseInt(darr[3]); int position = 0; if (darr.length >= 5) position = Integer.parseInt(darr[4]); AppDebug.Log(tag, type+"...fileindex=" + fileindex + ",position=" + position); Intent intent = new Intent(); intent.setAction(MainService.ACT_SYNC_PROGRESS); intent.putExtra("fileindex", fileindex); intent.putExtra("position", position); MainService.getAppContext().sendBroadcast(intent); } }
二.广播形式实现
1)受限广播它不被路由发送,但会被送到相同物理网络段上的所有主机IP地址的网络字段和主机字段
全为1就是地址255.255.255.255(假如路由器将此类地址数据转发出去全世界都能收到
你发出的消息想想都恐怖)
2)直接广播
网络广播会被路由,并会发送到专门网络上的每台主机IP地址的网络字段定义这个网络,
主机字段通常全为1,如 192.168.10.255 .
前面已经说了需要一台设备作为Server发出自己的进度,其他设备作为Client接收到数据后做相应的
处理所以有一个Server发出数据包,和多个Clinet接收相应的数据。
1.Server发起同步
//UDP广播形式发送 public static void DatagramClientSend(int port, String cmd) { String host = "255.255.255.255";//广播地址 DatagramSocket multiSocket; try { InetAddress adds = InetAddress.getByName(host); AppDebug.Log(tag, "发送广播信息:" + cmd); multiSocket = new DatagramSocket(); byte[] sendMSG = cmd.getBytes(); DatagramPacket dp = new DatagramPacket(sendMSG, sendMSG.length, adds, port); multiSocket.send(dp); multiSocket.close(); } catch (UnknownHostException e) { AppDebug.Log(tag, "发送广播信息...UnknownHostException"+e.getMessage()); e.printStackTrace(); } catch (SocketException e) { AppDebug.Log(tag, "发送广播信息...SocketException"+e.getMessage()); e.printStackTrace(); } catch (IOException e) { AppDebug.Log(tag, "发送广播信息...IOException"+e.getMessage()); e.printStackTrace(); } }
因为不知道大家的路由网关地址,所以就以255这个受限地址作为目标地址,方便大家导入查看效果。
2.Clinet接收数据包
//UDP广播形式接收 public void DatagramServerStart(int localPort) { int RECEIVE_LENGTH = 1024; try { DatagramSocket receiveDatagram = new DatagramSocket(localPort); DatagramPacket dp = new DatagramPacket(new byte[RECEIVE_LENGTH], RECEIVE_LENGTH); while (running) { receiveDatagram.receive(dp); String data = (new String(dp.getData())).substring(0, dp.getLength()); //获取数据包实际长度 String AutoSyncGroup = "1"; //自动同步播放广播组,默认为1 if (AutoSyncGroup == null || AutoSyncGroup.equals("")) AutoSyncGroup = "1"; AppDebug.Log(tag, "收到广播信息[" + dp.getLength() + "]:" + data); doDealData(data, AutoSyncGroup,"DatagramServerStart"); } receiveDatagram.close(); } catch (SocketException e) { AppDebug.Log(tag, "收到广播信息...SocketException"+e.getMessage()); e.printStackTrace(); } catch (IOException e) { AppDebug.Log(tag, "收到广播信息..IOException"+e.getMessage()); e.printStackTrace(); } }
三.组播形式实现
组播和广播实现上基本类似,但是需要加入组,Server和Clinet需要同时加入相同组播地址 joinGroup(InetAddress groupAddr) 才可以。1.Server发起同步
//UDP组播形式发送 public static boolean MulticastClientSend(int port, String cmd) { String destAddressStr = "224.1.2.3";//目标地址 int destPort = port; int TTL = 4; boolean ret = false; MulticastSocket multiSocket; try { InetAddress destAddress = InetAddress.getByName(destAddressStr); if (!destAddress.isMulticastAddress()) {// 检测该地址是否是多播地址 return false; } AppDebug.Log(tag, "发送组播信息:" + cmd); multiSocket = new MulticastSocket(); multiSocket.setTimeToLive(TTL); byte[] sendMSG = cmd.getBytes(); DatagramPacket dp = new DatagramPacket(sendMSG, sendMSG.length, destAddress, destPort); multiSocket.send(dp); multiSocket.close(); ret = true; } catch (IOException e) { e.printStackTrace(); } return ret; }
需要注意的是组播需要路由器支持,有的路由并没有严格按照的UPnP协议来实现所以会出现自己能收到消息别人收不到, 或者自己收不到别人也收不到等情况。
2.Clinet接收组播数据包
public void MulticastServerStart(int localPort) { String multicastHost = "224.1.2.3"; int RECEIVE_LENGTH = 1024; InetAddress receiveAddress; try { receiveAddress = InetAddress.getByName(multicastHost); int port = localPort; MulticastSocket receiveMulticast = new MulticastSocket(port); receiveMulticast.joinGroup(receiveAddress);//加入组播 DatagramPacket dp = new DatagramPacket(new byte[RECEIVE_LENGTH], RECEIVE_LENGTH); while (running) { receiveMulticast.receive(dp); String data = (new String(dp.getData())).substring(0, dp.getLength()); String AutoSyncGroup = "1"; //自动同步播放广播组,默认为1 if (AutoSyncGroup == null || AutoSyncGroup.equals("")) AutoSyncGroup = "1"; AppDebug.Log(tag, "收到组播信息[" + dp.getLength() + "]:" + data); doDealData(data, AutoSyncGroup,"MulticastServerStart"); } receiveMulticast.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
源码下载,点击这里
github地址:https://github.com/mythace/Udp_LAN_SysPlay 欢迎satr or fork .
相关文章推荐
- EasyPlayer Android基于ffmpeg实现播放(RTSP/RTMP/HTTP/HLS)同步录像功能
- android 简单的实现视频的播放 基于 ijkplayer的封装更加简单 方便快捷
- Android编程实现基于局域网udp广播自动建立socket连接的方法
- [置顶] Android开发实战使用(VR技术实现360°全景视频播放功能)
- android 简单的实现视频的播放 基于 ijkplayer的封装更加简单 方便快捷
- EasyPlayer Android基于ffmpeg实现播放(RTSP/RTMP/HTTP/HLS)同步录像功能
- [置顶] 【Android】Android开发实现进度条效果,SeekBar的简单使用。音量,音乐播放进度,视频播放进度等
- [置顶] 简述Android中如何实现播放视频形式的引导页面
- ubuntu下基于java环境实现的视频播放功能(一)视频播放组件
- Android实现歌曲播放时歌词同步显示具体思路
- Android之SurfaceView实现视频播放
- Unity3D 实现视频播放和声音同步(笔记)
- 基于android多媒体框架实现播放APE音频的实现
- Android的多媒体技术——MediaPlayer实现音频与视频的播放
- VB.NET C#实现基于UDP的免服务器局域网多客户端点对点通讯
- 基于Android的视频监控系统设计与实现
- Android 实现歌曲播放时歌词同步显示
- Android之SurfaceView实现视频播放
- Android之SurfaceView实现视频播放
- 基于C#的UDP协议的同步实现